Index: branches/features/taskProcedureRework/.classpath
===================================================================
--- branches/features/taskProcedureRework/.classpath	(revision 753)
+++ branches/features/taskProcedureRework/.classpath	(revision 753)
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+<classpathentry kind="src" path="src/java"/>
+<classpathentry kind="src" path="src/groovy"/>
+<classpathentry kind="src" path="grails-app/conf"/>
+<classpathentry kind="src" path="grails-app/controllers"/>
+<classpathentry kind="src" path="grails-app/domain"/>
+<classpathentry kind="src" path="grails-app/services"/>
+<classpathentry kind="src" path="grails-app/taglib"/>
+<classpathentry kind="src" path="test/integration"/>
+<classpathentry kind="src" path="test/unit"/>
+<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+<classpathentry kind="output" path="web-app/WEB-INF/classes"/>
+<classpathentry kind="var" path="GRAILS_HOME/ant/lib/ant.jar"/>
+<classpathentry kind="var" path="GRAILS_HOME/lib/slf4j-api-1.5.6.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jasper-runtime-5.5.15.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jsp-api-2.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/sitemesh-2.4.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-codec-1.3.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/oro-2.0.8.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/backport-util-concurrent-3.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-dbcp-1.2.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/start.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/ant-junit-1.7.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/ant-1.7.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/hsqldb-1.8.0.5.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jetty-plus-6.1.14.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/slf4j-log4j12-1.5.6.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/junit-3.8.2.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/spring-webmvc-2.5.6.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/org.springframework.webflow-2.0.3.RELEASE.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jstl-2.4.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/ehcache-1.5.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/xpp3_min-1.1.3.4.O.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/ivy-2.0.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jsp-api-2.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jetty-util-6.1.14.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jline-0.9.91.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jetty-naming-6.1.14.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/ant-nodeps-1.7.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-collections-3.2.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/standard-2.4.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/spring-2.5.6.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jasper-compiler-jdt-5.5.15.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/log4j-1.2.15.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/groovy-all-1.6.3.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/svnkit-1.2.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jcl-over-slf4j-1.5.6.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jta-1.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jetty-6.1.14.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/cglib-nodep-2.1_3.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/spring-test-2.5.6.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/standard-2.3.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-el-1.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/org.springframework.binding-2.0.3.RELEASE.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-validator-1.3.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/oscache-2.4.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/org.springframework.js-2.0.3.RELEASE.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/serializer.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/ognl-2.6.9.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/ant-trax.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/ant-launcher-1.7.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jsr107cache-1.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-fileupload-1.2.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jstl-2.3.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/servlet-api-2.5-6.1.14.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/jasper-compiler-5.5.15.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-lang-2.4.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/ejb3-persistence-3.3.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-beanutils-1.7.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-io-1.4.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/gant_groovy1.6-1.6.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/antlr-2.7.6.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-cli-1.0.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/lib/commons-pool-1.2.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/dist/grails-test-1.1.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/dist/grails-scripts-1.1.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/dist/grails-bootstrap-1.1.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/dist/grails-gorm-1.1.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/dist/grails-resources-1.1.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/dist/grails-crud-1.1.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/dist/grails-webflow-1.1.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/dist/grails-core-1.1.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/dist/grails-spring-1.1.1.jar" />
+<classpathentry kind="var" path="GRAILS_HOME/dist/grails-web-1.1.1.jar" />
+</classpath>
Index: branches/features/taskProcedureRework/.project
===================================================================
--- branches/features/taskProcedureRework/.project	(revision 753)
+++ branches/features/taskProcedureRework/.project	(revision 753)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>gnuMims</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.codehaus.groovy.eclipse.groovyBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.codehaus.groovy.eclipse.groovyNature</nature>
+	</natures>
+</projectDescription>
Index: branches/features/taskProcedureRework/COPYING
===================================================================
--- branches/features/taskProcedureRework/COPYING	(revision 753)
+++ branches/features/taskProcedureRework/COPYING	(revision 753)
@@ -0,0 +1,661 @@
+                    GNU AFFERO GENERAL PUBLIC LICENSE
+                       Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+  A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate.  Many developers of free software are heartened and
+encouraged by the resulting cooperation.  However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+  The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community.  It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server.  Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+  An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals.  This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU Affero General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Remote Network Interaction; Use with the GNU General Public License.
+
+  Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software.  This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time.  Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source.  For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code.  There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<http://www.gnu.org/licenses/>.
Index: branches/features/taskProcedureRework/INSTALL
===================================================================
--- branches/features/taskProcedureRework/INSTALL	(revision 753)
+++ branches/features/taskProcedureRework/INSTALL	(revision 753)
@@ -0,0 +1,14 @@
+GnuMims is a web application built with the Grails (www.grails.org) web framework. 
+To run from source a working Grails installation is required.
+To run from WAR (web application archive) a working Java servlet (e.g: Tomcat) is required.
+
+To run from source:
+ - cd $projectdir
+ - grails run-app
+
+To run from war:
+ - select and configure database.
+ - deploy to Java application server as per server instructions.
+
+See www.gnumims.org for more.
+http://www.gnumims.org/trac/wiki/Installing
Index: branches/features/taskProcedureRework/README
===================================================================
--- branches/features/taskProcedureRework/README	(revision 753)
+++ branches/features/taskProcedureRework/README	(revision 753)
@@ -0,0 +1,17 @@
+    GnuMims - A web application providing a Maintenance and Inventory Management Solution for your Assets.
+    Copyright (C) 2008-2010 Gavin Kromhout
+    Copyright (C) 2008-2010 Steven Tucker
+    Copyright (C) 2008-2010 Raymond Smith
+
+    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/>
Index: branches/features/taskProcedureRework/application.properties
===================================================================
--- branches/features/taskProcedureRework/application.properties	(revision 753)
+++ branches/features/taskProcedureRework/application.properties	(revision 753)
@@ -0,0 +1,19 @@
+#Grails Metadata file
+#Wed Jun 02 11:20:51 EST 2010
+app.grails.version=1.2.2
+app.name=gnuMims
+app.servlet.version=2.4
+app.vcsRevision=$Rev$
+app.version=
+plugins.acegi=0.5.2
+plugins.class-diagram=0.5.1
+plugins.export=0.6
+plugins.filterpane=0.6.8
+plugins.help-balloons=1.3
+plugins.hibernate=1.2.2
+plugins.jasper=0.9.7
+plugins.navigation=1.1.1
+plugins.quartz=0.4.2
+plugins.richui=0.8
+plugins.searchable=0.5.5
+plugins.tomcat=1.2.2
Index: branches/features/taskProcedureRework/doc/DatabaseDesign.tex
===================================================================
--- branches/features/taskProcedureRework/doc/DatabaseDesign.tex	(revision 753)
+++ branches/features/taskProcedureRework/doc/DatabaseDesign.tex	(revision 753)
@@ -0,0 +1,65 @@
+\documentclass[12pt,a4paper]{article}
+\usepackage{inputenc}
+\usepackage{color}
+\usepackage{graphicx}
+\author{Gavin Kromhout and Steven Tucker}
+\title{GnuMims Database Design}
+\date{09 November 2008}
+%\date{\today{}}
+
+\begin{document}
+%Turn off section numbers
+\setcounter{secnumdepth}{-1}
+%Need this else header formatting vanishes.
+\maketitle {}
+
+
+\section{Intro}
+ Many organisations use a ``database''.
+ Maintenace departments often buy very expensive and customised software to monitor and improve their maintenace activities.
+ There are many advantages to using a database.
+ This is our attempt to create GnuMims, for open source Maintenace and Inventory Management.
+
+
+\section{Common requirements}
+\begin{itemize}
+ \item Easy install, must have a running demo within a few commands.
+  \subitem Scripted, packaged and/or web framework.
+ \item Open source, GNU GPL.
+  \subitem Leverage the best of open source for fast development
+  \subitem and ease of maintenance.
+ \item SVN and FTP/SSH for collaboration.
+ \item Grails web framework.
+  \item Architecture MVC
+%TODO:
+\textcolor{red}
+{
+ \item Specify naming convention for database and code.
+ \item Maintain Project Flowcharts, ERD, Database Schema, BLL and Documentation.
+  \subitem Use Dia, flowcharts, recall etc.
+}
+\end{itemize}
+
+\section{Project Management Flowchart}
+\begin{center}
+ \includegraphics[scale=0.75]{ProjectManagementFlowchart.png}
+\end{center}
+
+\section{Entity Relationship Diagram}
+\begin{center}
+ \includegraphics[scale=0.25]{gnuMimsErd.png}
+\end{center}
+
+\section{Core Scope}
+\textcolor{red}
+{
+Determine the core scope as per ERD.
+Determine the initial scope as per ERD.
+Indicate standalone packages.
+}
+
+\begin{center}
+The end.
+\end{center}
+
+\end{document}
Index: branches/features/taskProcedureRework/doc/Definitions/EntryTerms.txt
===================================================================
--- branches/features/taskProcedureRework/doc/Definitions/EntryTerms.txt	(revision 753)
+++ branches/features/taskProcedureRework/doc/Definitions/EntryTerms.txt	(revision 753)
@@ -0,0 +1,45 @@
+Entry terms and definitions.
+
+Entry class attributes:
+
+    comment
+                - Default = required so nothing.
+                - Larger text area.
+                - What was done for this entry.
+
+    dateDone
+                - Default = now.
+                - Precision = day.
+                - Can be changed.
+                - Date that person is reporting as the date entry was done.
+
+    dateEntered
+                - Default = now.
+                - Precision = second.
+                - Cannot be changed.
+                - Date the entry was actually entered.
+
+    durationHour
+                - Default = 0.
+                - Integer representing hours spent on this entry.
+
+    durationMinute
+                - Default = 0 
+                - Integer representing minutes spent on this entry.
+
+    enteredBy
+                - Default = current person.
+                - Cannot be changed.
+                - Of Class Person.
+
+    task        
+                - The task this entry belongs to.
+                - Of Class Task.
+
+    entryType
+                - Default = one of "Work Done", "Fault", "Production Note", "Work Request".
+                - Default depends on where the entry comes from.
+                - Of Class EntryType.
+
+#Required actions.
+Return a list of all entries for a Task.
Index: branches/features/taskProcedureRework/doc/Definitions/InventoryTerms.txt
===================================================================
--- branches/features/taskProcedureRework/doc/Definitions/InventoryTerms.txt	(revision 753)
+++ branches/features/taskProcedureRework/doc/Definitions/InventoryTerms.txt	(revision 753)
@@ -0,0 +1,87 @@
+Inventory terms and definitions.
+
+InventoryItem:
+    name
+                - Default = required so nothing.
+                - Standard length used most places.
+
+    description
+                - Default = "".     
+                - Longer for additional info only shown in detail views.
+
+    isActive    
+                - Default=true, false if "Trashed".
+                - Set false by Trash action.
+                - Set true by Restore action. 
+                - Require true when creating new entries/lists for dropdowns etc.
+                - Ignore when viewing old associations or creating lists for searching etc.
+
+    isObsolete    
+                - Default=false.
+                - Is this InventoryItem now considered obsolete by the manufacturer.
+
+    manufacturersPartNumber
+                - Default = "".     
+                - The part number that the manufacturer uses to identify this InventoryItem.
+
+    suppliersPartNumber
+                - Default = "".     
+                - The part number that the supplier uses to identify this InventoryItem.
+
+    enableReorder    
+                - Default=true.
+                - Should this InventoryItem appear on reorder and auto order lists.
+
+    reorderPoint
+                - Required so no default.
+                - Once total StoredItems equals this point the item will appear on reorder and auto order lists.
+
+    recommendedReorderPoint
+                - Provided the required information is available a recommendedReorderPoint is calculated.
+
+    averageDeliveryTime
+                - The average delivery time in days from placement of reorder.
+
+   inventoryGroup
+                - Default = required so nothing.
+                - The InventoryGroup this InventoryItem belongs to.
+                - Initially one of "Misc", "Mechanical", "Electrical", "Production", "Raw Materials".
+                - Of Class InventoryGroup.
+
+    inventoryType
+                - Default = required so nothing.
+                - Initially one of "Consumable", "Repairable".
+                - Of Class InventoryType.
+
+    unitOfMeasure
+                - Default = required so nothing.
+                - Initially one of "each", "meter(s)", "box(es)", "litre(s)"
+                - Of Class UnitOfMeasure.
+
+    alternateItems
+                - An InventoryItem may have many alternateItems of Class InventoryItem.
+                - Indicates that this InventoryItem has alternatives.
+
+    spareFor
+                - An InventoryItem may have many assets that it is a spare for, of Class Asset.
+
+    storedItems
+                - An InventoryItem may have many StoredItems of Class StoredItem.
+
+    inventoryMovements
+                - An InventoryItem may have many InventoryMovements of Class InventoryMovement.
+
+    manufacturers
+                - An InventoryItem may have many Manufacturers of the Class Manufacturer.
+
+    suppliers
+               - An InventoryItem may have many Suppliers of the Class Supplier.
+
+
+#External required actions.
+Calculate/Show total storedItems.
+
+InventoryMovementType
+    Initially one of "Used", "Received", "Repaired"
+
+
Index: branches/features/taskProcedureRework/doc/Definitions/PreventativeMaintenance_PM.txt
===================================================================
--- branches/features/taskProcedureRework/doc/Definitions/PreventativeMaintenance_PM.txt	(revision 753)
+++ branches/features/taskProcedureRework/doc/Definitions/PreventativeMaintenance_PM.txt	(revision 753)
@@ -0,0 +1,17 @@
+Preventative Maintenance or PM
+
+ * A PM is simply a task where:
+  * Task type = "Preventative Maintenance"
+  * As with any task a PM may have a recurring schedule, procedure and entries etc.
+
+The following information can be automatically returned from the system.
+
+ * PM frequency = Task.taskRecurringSchedule
+
+ * PM KPI's:
+  * Total PM's = Task.findAllByTaskType("Preventative Maintenance")
+  * Complete PM's = Total.findAllByTaskStatus("Complete")
+  * PM completetion rate = Complete/Total
+  * Missed PM's = Total - Complete
+
+ * Find all Recurring PM tasks = context{TaskRecShed.task.taskType("Preventative Maintenance") and Date in range}
Index: branches/features/taskProcedureRework/doc/Definitions/TaskActions.txt
===================================================================
--- branches/features/taskProcedureRework/doc/Definitions/TaskActions.txt	(revision 753)
+++ branches/features/taskProcedureRework/doc/Definitions/TaskActions.txt	(revision 753)
@@ -0,0 +1,45 @@
+Action          Modification (dates have precision='second')        Task (dates have precision='$day')
+------------------------------------------------------------------------------------------------------
+
+Create      ->  recordModification("Created")                       <-  is the date created.
+
+Schedule    ->  recordModification("SetTargetStartDate")            ->  set: Task.targetStartDate
+
+                recordModification("SetTargetCompletionDate")       ->  set: Task.targetCompletionDate
+
+Start       ->  recordModification("ActualStartDate")               <-  is the date started
+
+Complete    ->  recordModification("ActualCompletionDate")          <-  is the date completed   
+
+Reopen    ->  recordModification("ActualCompletionDate")          <-  is the date completed   
+                   
+Delete      ->  recordModification("Deleted")                       ->  Task.isActive = false
+Trash       ->  recordModification("Trashed")                       ->  Task.isActive = false
+                 
+Restore    ->  recordModification("Restore")                        ->  Task.isActive = true
+                
+Approve     ->  recordModification("Approve")                       ->  Task.isApproved = true
+                
+Renege      ->  recordModification("Renege")                        ->  Task.isApproved = false
+
+AddAssignedPerson->  recordModification("AddAssignedPerson", $assignedPerson)
+
+RmAssignedPerson ->  recordModification("RmAssignedPerson", $assignedPerson)
+
+recordModification(String type) {
+    Modification.modificationType = ModificationType.findByName(type)
+    Modification.date = now
+    Modification.person = userName                                     
+    Modification.comment = ""  
+}
+recordModification(String type, String comment) {
+    Modification.modificationType = ModificationType.findByName(type)
+    Modification.date = now
+    Modification.person = userName                                      
+    Modification.comment = comment  
+}                     
+
+
+Required Services:
+TaskCopy
+TaskGenerateSubTask                                      
Index: branches/features/taskProcedureRework/doc/Definitions/TaskTerms.txt
===================================================================
--- branches/features/taskProcedureRework/doc/Definitions/TaskTerms.txt	(revision 753)
+++ branches/features/taskProcedureRework/doc/Definitions/TaskTerms.txt	(revision 753)
@@ -0,0 +1,137 @@
+Intro
+
+ * Tasks may have one parent task and many sub tasks.
+ * Tasks may have a recurring schedule.
+ * Tasks with an enabled recurring schedule automatically generate subTasks.
+ * Tasks may have many "work done" or "fault" entries.
+
+Task terms and definitions.
+
+Task:
+    description
+                - Default = required so nothing.
+                - Standard length used most places.
+
+    comment
+                - Default = "".     
+                - Longer for additional info only shown in detail views.
+
+    targetStartDate
+                - Default = now.
+                - The date we would like task to start.
+                - Set by Schedule action.
+                - Set to now for Unscheduled Breakin.
+
+    targetCompletionDate
+                - Default = now.
+                - The date we would like task to be completed by.
+                - Set by Schedule action.
+                - Set to now for Unscheduled Breakin.
+
+    isScheduled 
+                - Default = false.
+                - Set true by Schedule action.
+
+    isApproved  
+                - Default=false, true when approved.
+                - Set true by Approve action
+                - Set false by Renege action.
+
+    isActive    
+                - Default=true, false if "Deleted".
+                - Set false by Delete action.
+                - Set true by Undelete action. 
+                - Require true when creating new entries/lists for dropdowns etc.
+                - Ignore when viewing old associations or creating lists for searching etc.
+
+    taskGroup
+                - Default = required so nothing.
+                - The taskGroup this task belongs to.
+                - Of Class TaskGroup.
+
+    taskStatus
+                - Default = "Not Started".
+                - The current status of this task.
+                - Of Class TaskStatus.
+                - One of "Not Started", "In Progress" or "Completed".
+                - Automagically set to "In Progress" on first "Work Done" entry.
+                - Automagically set to "Completed" by action button.
+
+    taskPriority
+                - Default = Normal.
+                - Of Class TaskPriority.
+                - One of Normal, Low, High, Immediate.
+                - Automagically set to High if Unscheduled Breakin?
+                - Automagically set to ?
+
+    taskType
+                - Default = required so nothing.
+                - Of Class TaskType.
+                - Automagically set to ?
+
+    parentTask
+                - Default = not always used so nothing.
+                - Indicates that this is a subTask and links back to the parentTask.
+                - Of Class Task.
+
+    leadPerson  
+                - Default = current person.
+                - The primay contact person.
+                - Of Class Person.
+
+    primaryAsset  
+                - The primay asset that costs will be assigned to.
+                - Of Class Asset
+
+    entries       
+                - A task may have many entries of Class Entry.
+                - Persons other than the leadPerson or assingedPersons may create entries.
+    
+    modifications
+                - A task may have many modifications of Class Modification.
+
+    assignedPersons
+                - A task may have many assingedPersons of Class Person.
+                - estimatedHour and estimatedMinute.
+
+    subTasks    
+                - A task may have many subTasks of Class Task.
+                - The parentTask value must be set in the subTask.
+
+    associatedAssets    
+                - A task may have many associatedAssets of Class Asset.
+                - No costs are assigned to these assets this is for reference purposes.
+
+    inventoryMovements
+                - A task may have many inventoryMovements of Class InventoryMovement.
+
+
+#Calculated dates
+actualStartDate
+actualCompletionDate
+
+TaskType
+    Unscheduled Breakin - all work that was not scheduled, breakdowns/callouts.
+    Planned Maintenance - Planned work that is scheduled.
+    Project             - Capital expenditure upgrades or additions.
+    Turnaround          - Shutdowns, rebuilds, non Cap-Ex upgrades or additions.
+    Production Run      - Planned production that is scheduled?
+
+TaskGroup
+    ....                - custom used to groups tasks?
+    Engineering Activites
+    Production Activites
+    New Projects
+    ....                - specific shut group or turnaround etc.
+
+#Calculate missed state? 
+Missed() {
+    actualCompletionDate > targetCompletionDate
+}
+
+#External required actions.
+Show all modifications for a task.
+Show all assignedPersons for a task.
+Show all entries for a task.
+
+
Index: branches/features/taskProcedureRework/grails-app/conf/BootStrap.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/conf/BootStrap.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/conf/BootStrap.groovy	(revision 753)
@@ -0,0 +1,39 @@
+class BootStrap
+{
+    def createDataService
+
+    def init = { servletContext ->
+
+        /** Environment specific settings.
+        * Note that (circa grails-1.2.2) if running "test test-app integration:" from "grails interactive"
+        * the correct environment is applied for DataSource and Config,
+        * but for BootStrap (and others) the development environment is applied.
+        */
+        environments {
+            development {
+                log.info "Starting DEVELOPMENT bootstrap."
+                createDataService.ensureSystemAndAdminAccess()
+                createDataService.createBaseData()
+                createDataService.createDemoData()
+                createDataService.startSearchableIndex()
+            }
+            test {
+                log.info "Starting TEST bootstrap."
+                createDataService.ensureSystemAndAdminAccess()
+                createDataService.createBaseData()
+                createDataService.startSearchableIndex(false)
+            }
+            production {
+                log.info "Starting PRODUCTION bootstrap."
+                createDataService.ensureSystemAndAdminAccess()
+                createDataService.createBaseData()
+                createDataService.startSearchableIndex()
+            }
+        }
+
+    } // init
+
+    def destroy = {
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/conf/BuildConfig.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/conf/BuildConfig.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/conf/BuildConfig.groovy	(revision 753)
@@ -0,0 +1,92 @@
+grails.project.class.dir = "target/classes"
+grails.project.test.class.dir = "target/test-classes"
+grails.project.test.reports.dir	= "target/test-reports"
+
+def env = System.getProperty('grails.env')
+
+switch (env) {
+    case "production":
+        //grails.project.war.file = "target/${appName}-${appVersion}.war"
+        grails.project.war.file="target/${appName}Live.war"
+        break
+    case "development":
+        grails.project.war.file="target/${appName}Dev.war"
+        break
+    default:
+        grails.project.war.file="target/${appName}.war"
+        break
+}
+
+grails.war.resources = { stagingDir, args ->
+    // Remove some duplicate jars.
+    delete file: "${stagingDir}/WEB-INF/lib/jasperreports-2.0.5.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/jasperreports-3.1.2.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/aspectjrt-1.5.4.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/commons-digester-1.7.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/iText-2.0.8.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/iText-2.1.5.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/jfreechart-1.0.3.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/poi-3.0.2-FINAL-20080204.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/facebook-2.0.4.jar"
+    // Included by searchable plugin.
+    delete file: "${stagingDir}/WEB-INF/lib/compass-2.1.0.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/compass-2.1.0-src.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/lucene-core.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/lucene-analyzers.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/lucene-highlighter.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/lucene-queries.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/lucene-snowball.jar"
+    delete file: "${stagingDir}/WEB-INF/lib/lucene-spellchecker.jar"
+}
+
+grails.project.dependency.resolution = {
+
+    // inherit Grails' default dependencies
+    inherits( "global" ) {
+        // uncomment to disable ehcache
+        // excludes 'ehcache'
+    }
+
+    log "warn" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
+
+    repositories {
+        grailsPlugins()
+        grailsHome()
+
+        // uncomment the below to enable remote dependency resolution
+        // from public Maven repositories
+        //mavenLocal()
+        mavenCentral()
+        //mavenRepo "http://snapshots.repository.codehaus.org"
+        //mavenRepo "http://repository.codehaus.org"
+        //mavenRepo "http://download.java.net/maven/2/"
+        //mavenRepo "http://repository.jboss.com/maven2/"
+    }
+
+    dependencies {
+        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
+
+        runtime 'mysql:mysql-connector-java:5.1.9'
+
+        runtime ('org.apache.poi:poi:3.5-FINAL') {
+            excludes 'servlet-api', 'commons-logging', 'log4j'
+        }
+
+        runtime ('net.sf.jasperreports:jasperreports:3.7.2') {
+            excludes 'xml-apis'
+        }
+
+        runtime ('org.compass-project:compass:2.1.4')
+        runtime ('org.apache.lucene:lucene-core:2.4.1')
+        runtime ('org.apache.lucene:lucene-analyzers:2.4.1')
+        runtime ('org.apache.lucene:lucene-highlighter:2.4.1')
+        runtime ('org.apache.lucene:lucene-queries:2.4.1')
+        runtime ('org.apache.lucene:lucene-snowball:2.4.1')
+        runtime ('org.apache.lucene:lucene-spellchecker:2.4.1')
+
+        runtime ('org.apache.ant:ant:1.7.1')
+        runtime ('org.apache.ant:ant-launcher:1.7.1')
+
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/conf/Config.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/conf/Config.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/conf/Config.groovy	(revision 753)
@@ -0,0 +1,409 @@
+// locations to search for config files that get merged into the main config
+// config files can either be Java properties files or ConfigSlurper scripts
+
+// grails.config.locations = [ "classpath:${appName}-config.properties",
+//                             "classpath:${appName}-config.groovy",
+//                             "file:${userHome}/.grails/${appName}-config.properties",
+//                             "file:${userHome}/.grails/${appName}-config.groovy"]
+
+// if(System.properties["${appName}.config.location"]) {
+//    grails.config.locations << "file:" + System.properties["${appName}.config.location"]
+// }
+grails.mime.file.extensions = true // enables the parsing of file extensions from URLs into the request format
+grails.mime.types = [ html: ['text/html','application/xhtml+xml'],
+                      xml: ['text/xml', 'application/xml'],
+                      text: 'text-plain',
+                      js: 'text/javascript',
+                      rss: 'application/rss+xml',
+                      atom: 'application/atom+xml',
+                      css: 'text/css',
+                      csv: 'text/csv',
+                      pdf: 'application/pdf',
+                      rtf: 'application/rtf',
+                      excel: 'application/vnd.ms-excel',
+                      ods: 'application/vnd.oasis.opendocument.spreadsheet',
+                      all: '*/*',
+                      json: ['application/json','text/json'],
+                      form: 'application/x-www-form-urlencoded',
+                      multipartForm: 'multipart/form-data'
+                    ]
+// The default codec used to encode data with ${}
+grails.views.default.codec="none" // none, html, base64
+grails.views.gsp.encoding="UTF-8"
+grails.converters.encoding="UTF-8"
+
+// enable Sitemesh preprocessing of GSP pages
+grails.views.gsp.sitemesh.preprocess = true
+// scaffolding templates configuration
+grails.scaffolding.templates.domainSuffix = 'Instance'
+
+// Set to false to use the new Grails 1.2 JSONBuilder in the render method
+grails.json.legacy.builder=false
+
+// enabled native2ascii conversion of i18n properties files
+grails.enable.native2ascii = true
+
+// whether to install the java.util.logging bridge for sl4j. Disable fo AppEngine!
+grails.logging.jul.usebridge = true
+// packages to include in Spring bean scanning
+grails.spring.bean.packages = []
+
+/**
+* Internal searchable index config.
+*/
+// Is set true by createDataService.startSearchableIndex() once bootstrap completes.
+appSearchable.cascadeOnUpdate = false
+
+/**
+* Directory configuration.
+* Pickup the Tomcat/Catalina directory else use the target or current dir.
+*/
+def fs = File.separator // Local variable.
+globalDirs.targetDir = new File("target${fs}").isDirectory() ? "target${fs}" : ''
+globalDirs.catalinaBase = System.properties.getProperty('catalina.base')
+globalDirs.logDirectory = globalDirs.catalinaBase ? "${globalDirs.catalinaBase}${fs}logs${fs}" : globalDirs.targetDir
+globalDirs.workDirectory = globalDirs.catalinaBase ? "${globalDirs.catalinaBase}${fs}work${fs}" : globalDirs.targetDir
+globalDirs.tempDirectory = globalDirs.catalinaBase ? "${globalDirs.catalinaBase}${fs}temp${fs}${appName}${fs}" : globalDirs.targetDir
+globalDirs.searchableIndexDirectory = "${globalDirs.workDirectory}SearchableIndex${fs}${appName}${fs}"
+globalDirs.tempInventoryItemPicturesDirectory = "${globalDirs.tempDirectory}InventoryItemPictures${fs}"
+
+/**
+ * Log4j configuration.
+ * Causing this file to reload (e.g. edit+save) may break the appLog destination
+ * and further logs will be written to files or directories like "[:]".
+ * For more info see http://logging.apache.org/log4j/1.2/manual.html
+ * For log levels see http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Level.html
+ * Basic log levels are ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
+ */
+
+log4j = {
+    appenders {
+        // Use if we want to prevent creation of a stacktrace.log file.
+        'null' name:'stacktrace'
+
+        // Use this if we want to modify the default appender called 'stdout'.
+        console name:'stdout', layout:pattern(conversionPattern: '[%t] %-5p %c{2} %x - %m%n')
+
+        // Custom log file.
+        rollingFile name:"appLog",
+                        file:"${globalDirs.logDirectory}${appName}.log".toString(),
+                        maxFileSize:'300kB',
+                        maxBackupIndex:1,
+                        layout:pattern(conversionPattern: '%d{[EEE, dd-MMM-yyyy @ HH:mm:ss.SSS]} [%t] %-5p %c %x - %m%n')
+    }
+
+    // This is for the built-in stuff and from the default Grails-1.2.1 config.
+    error 'org.codehaus.groovy.grails.web.servlet',  //  controllers
+            'org.codehaus.groovy.grails.web.pages', //  GSP
+            'org.codehaus.groovy.grails.web.sitemesh', //  layouts
+            'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
+            'org.codehaus.groovy.grails.web.mapping', // URL mapping
+            'org.codehaus.groovy.grails.commons', // core / classloading
+            'org.codehaus.groovy.grails.plugins', // plugins
+            'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
+            'org.springframework',
+            'org.hibernate',
+            'net.sf.ehcache.hibernate'
+
+    warn   'org.mortbay.log' // Jetty
+
+    error 'grails.app' // Set the default log level for our app code.
+    info 'grails.app.bootstrap' // Set the log level per type and per type.class
+    error 'grails.app.service.AuthService'
+    error 'grails.app.service.NavigationService'
+    error 'grails.app.service.com.zeddware.grails.plugins.filterpane.FilterService'
+    info 'org.codehaus.groovy.grails.plugins.searchable'
+    //info 'org.compass'
+    error 'grails.app.task' // Quartz jobs.
+    info 'grails.app.task.InventoryIndexJob'
+
+    // Move anything that should behave differently into this section.
+    switch(environment) {
+        case 'development':
+            // Configure the root logger to output to stdout and appLog appenders.
+            root {
+                error 'stdout','appLog'
+                additivity = true
+            }
+            //debug "org.hibernate.SQL"
+            debug 'grails.app.service'
+            debug 'grails.app.controller'
+            break
+        case 'test':
+            // Configure the root logger to only output to appLog appender.
+            root {
+                error 'stdout','appLog'
+                additivity = true
+            }
+            debug 'grails.app.service'
+            debug 'grails.app.controller'
+            break
+        case 'production':
+            // Configure the root logger to only output to appLog appender.
+            root {
+                error 'appLog'
+                additivity = true
+            }
+            warn 'grails.app.service'
+            warn 'grails.app.controller'
+            debug 'grails.app.service.AssetCsvService'
+            debug 'grails.app.service.PersonCsvService'
+            debug 'grails.app.service.InventoryCsvService'
+            info 'grails.app.service.InventoryItemService'
+            debug 'grails.app.service.AssetTreeService' /// @todo: remove after testing.
+            break
+    }
+}
+
+/**
+ * Environment specific configuration.
+ */
+environments {
+
+    production {
+        grails.serverURL = "http://www.changeme.com" // Set serverURL stem for creating absolute links.
+    }
+
+    development {
+        grails.serverURL = "http://localhost:8080/${appName}" // Set serverURL stem for creating absolute links.
+    }
+
+    test {
+        grails.serverURL = "http://localhost:8080/${appName}" // Set serverURL stem for creating absolute links.
+    }
+
+} // end environments
+
+/**
+ * Navigation plugin menu.
+ * The top level titles are taken from i18n message bundles.
+ * Subitems i18n message bundles are not currently resolving with this plugin.
+ */
+navigation.nav = [
+    [order:10, controller:'appCore', title:'home', action:'start',
+        subItems: [
+            [order:10, controller:'appCore', title:'Start', action:'start', isVisible: { true }],
+            [order:20, controller:'appCore', title:'Manager', action:'manager', isVisible: {
+                    authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager,ROLE_InventoryManager,ROLE_AssetManager,ROLE_ProductionManager')
+                }
+            ],
+            [order:30, controller:'appCore', title:'Admin', action:'appAdmin', isVisible: { authenticateService.ifAllGranted('ROLE_AppAdmin') }],
+            [order:90, controller:'appCore', title:'Timeout', action:'changeSessionTimeout', isVisible: { params.action == 'changeSessionTimeout' }],
+            [order:91, controller:'appCore', title:'Password', action:'changePassword', isVisible: { params.action == 'changePassword' }],
+        ]
+    ],
+    [order:20, controller:'taskDetailed', title:'tasks', action:'search',
+        subItems: [
+            [order:10, controller:'taskDetailed', title:'Search', action:'search', isVisible: { true }],
+            [order:11, controller:'taskDetailed', title:'Calendar', action:'searchCalendar', isVisible: { true }],
+            [order:20, controller:'taskDetailed', title:'+Scheduled', action:'create', isVisible: { true }],
+            [order:30, controller:'taskDetailed', title:'+Unsheduled', action:'createUnscheduled', isVisible: { true }],
+            [order:40, controller:'taskDetailed', title:'+Callout', action:'createImmediateCallout', isVisible: { true }],
+            [order:90, controller:'taskDetailed', title:'Show', action:'show', id:'nav', isVisible: { params.action == 'show' }],
+            [order:91, controller:'taskDetailed', title:'Edit', action:'edit', id:'nav', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:30, controller:'inventoryItemDetailed', title:'inventory', action:'search',
+        subItems: [
+            [order:10, controller:'inventoryItemDetailed', title:'Search', action:'search', isVisible: { true }],
+            [order:20, controller:'inventoryItemDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'inventoryItemDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'inventoryItemDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }],
+            [order:91, controller:'inventoryItemDetailed', title:'Reorder', action:'reorder', isVisible: { params.action == 'reorder' }]
+        ]
+    ],
+    [order:40, controller:'assetDetailed', title:'assets', action:'search',
+        subItems: [
+            [order:10, controller:'assetDetailed', title:'Search', action:'search', isVisible: { true }],
+            [order:20, controller:'assetDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'assetDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'assetDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }],
+            [order:99, controller:'assetSubItemDetailed', title:'Sub Items', action:'search', isVisible: { true }]
+        ]
+    ]
+]
+
+/**
+ * Navigation plugin alternate menu.
+ * The alternate menu top level titles are not displayed anywhere.
+ * Subitems i18n message bundles are not currently resolving with this plugin.
+ */
+navigation.navAlt = [
+    [order:10, controller:'person', title:'person', action:'list',
+        subItems: [
+            [order:10, controller:'person', title:'Person List', action:'list', isVisible: { true }],
+            [order:20, controller:'person', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'person', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'person', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:20, controller:'taskProcedureDetailed', title:'taskProcedure', action:'list',
+        subItems: [
+            [order:10, controller:'taskProcedureDetailed', title:'Task Procedure List', action:'list', isVisible: { true }],
+            [order:20, controller:'taskProcedureDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'taskProcedureDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'taskProcedureDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:30, controller:'assetSubItemDetailed', title:'assetSubItem', action:'search',
+        subItems: [
+            [order:10, controller:'assetSubItemDetailed', title:'Sub Item Search', action:'search', isVisible: { true }],
+            [order:20, controller:'assetSubItemDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'assetSubItemDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'assetSubItemDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:40, controller:'maintenancePolicyDetailed', title:'maintenancePolicy', action:'list',
+        subItems: [
+            [order:10, controller:'maintenancePolicyDetailed', title:'Maintenance Policy List', action:'list', isVisible: { true }],
+            [order:20, controller:'maintenancePolicyDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'maintenancePolicyDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'maintenancePolicyDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:50, controller:'supplierDetailed', title:'supplier', action:'list',
+        subItems: [
+            [order:10, controller:'supplierDetailed', title:'Supplier List', action:'list', isVisible: { true }],
+            [order:20, controller:'supplierDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'supplierDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'supplierDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:70, controller:'inventoryStoreDetailed', title:'inventoryStore', action:'list',
+        subItems: [
+            [order:10, controller:'inventoryStoreDetailed', title:'Inventory Store List', action:'list', isVisible: { true }],
+            [order:20, controller:'inventoryStoreDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'inventoryStoreDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'inventoryStoreDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:80, controller:'inventoryLocationDetailed', title:'inventoryLocation', action:'list',
+        subItems: [
+            [order:10, controller:'inventoryLocationDetailed', title:'Inventory Location List', action:'list', isVisible: { true }],
+            [order:20, controller:'inventoryLocationDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'inventoryLocationDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'inventoryLocationDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:90, controller:'inventoryGroupDetailed', title:'inventoryGroup', action:'list',
+        subItems: [
+            [order:10, controller:'inventoryGroupDetailed', title:'Inventory Group List', action:'list', isVisible: { true }],
+            [order:20, controller:'inventoryGroupDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'inventoryGroupDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'inventoryGroupDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:110, controller:'supplierTypeDetailed', title:'supplierType', action:'list',
+        subItems: [
+            [order:10, controller:'supplierTypeDetailed', title:'Supplier Type List', action:'list', isVisible: { true }],
+            [order:20, controller:'supplierTypeDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'supplierTypeDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'supplierTypeDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:120, controller:'siteDetailed', title:'site', action:'list',
+        subItems: [
+            [order:10, controller:'siteDetailed', title:'Site List', action:'list', isVisible: { true }],
+            [order:20, controller:'siteDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'siteDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'siteDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:130, controller:'sectionDetailed', title:'section', action:'list',
+        subItems: [
+            [order:10, controller:'sectionDetailed', title:'Section List', action:'list', isVisible: { true }],
+            [order:20, controller:'sectionDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'sectionDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'sectionDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:140, controller:'extendedAttributeTypeDetailed', title:'extendedAttributeType', action:'list',
+        subItems: [
+            [order:10, controller:'extendedAttributeTypeDetailed', title:'Attribute Type List', action:'list', isVisible: { true }],
+            [order:20, controller:'extendedAttributeTypeDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'extendedAttributeTypeDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'extendedAttributeTypeDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:150, controller:'departmentDetailed', title:'department', action:'list',
+        subItems: [
+            [order:10, controller:'departmentDetailed', title:'Department List', action:'list', isVisible: { true }],
+            [order:20, controller:'departmentDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'departmentDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'departmentDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:160, controller:'productionReferenceDetailed', title:'productionReference', action:'list',
+        subItems: [
+            [order:10, controller:'productionReferenceDetailed', title:'Production Reference List', action:'list', isVisible: { true }],
+            [order:20, controller:'productionReferenceDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'productionReferenceDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'productionReferenceDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:170, controller:'costCodeDetailed', title:'costCode', action:'list',
+        subItems: [
+            [order:10, controller:'costCodeDetailed', title:'Cost Code List', action:'list', isVisible: { true }],
+            [order:20, controller:'costCodeDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'costCodeDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'costCodeDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:180, controller:'personGroupDetailed', title:'personGroup', action:'list',
+        subItems: [
+            [order:10, controller:'personGroupDetailed', title:'Person Group List', action:'list', isVisible: { true }],
+            [order:20, controller:'personGroupDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'personGroupDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'personGroupDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:190, controller:'personGroupTypeDetailed', title:'personGroupType', action:'list',
+        subItems: [
+            [order:10, controller:'personGroupTypeDetailed', title:'Person Group Type List', action:'list', isVisible: { true }],
+            [order:20, controller:'personGroupTypeDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'personGroupTypeDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'personGroupTypeDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:200, controller:'taskGroupDetailed', title:'taskProcedure', action:'list',
+        subItems: [
+            [order:10, controller:'taskGroupDetailed', title:'Task Group List', action:'list', isVisible: { true }],
+            [order:20, controller:'taskGroupDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'taskGroupDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'taskGroupDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:210, controller:'unitOfMeasureDetailed', title:'unitOfMeasure', action:'list',
+        subItems: [
+            [order:10, controller:'unitOfMeasureDetailed', title:'Unit Of Measure List', action:'list', isVisible: { true }],
+            [order:20, controller:'unitOfMeasureDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'unitOfMeasureDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'unitOfMeasureDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:220, controller:'inventoryItemPurchaseDetailed', title:'inventoryItemPurchase', action:'search',
+        subItems: [
+            [order:10, controller:'inventoryItemPurchaseDetailed', title:'Purchase Search', action:'search', isVisible: { true }],
+            [order:20, controller:'inventoryItemPurchaseDetailed', title:'Order', action:'create', isVisible: { true }],
+            [order:90, controller:'inventoryItemPurchaseDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'inventoryItemPurchaseDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ],
+    [order:230, controller:'purchasingGroupDetailed', title:'purchasingGroup', action:'list',
+        subItems: [
+            [order:10, controller:'purchasingGroupDetailed', title:'Purchasing Group List', action:'list', isVisible: { true }],
+            [order:20, controller:'purchasingGroupDetailed', title:'Create', action:'create', isVisible: { true }],
+            [order:90, controller:'purchasingGroupDetailed', title:'Show', action:'show', isVisible: { params.action == 'show' }],
+            [order:91, controller:'purchasingGroupDetailed', title:'Edit', action:'edit', isVisible: { params.action == 'edit' }]
+        ]
+    ]
+]
+
+/**
+ * Custom application global settings.
+ * @todo: externalise these settings to a config file (along with the database settings) or have them configurable via the web interface+database.
+ */
+taskRecurringScheduleJob.repeatInterval=10
+// It is recommended to limit the currencyList to the one that the site uses e.g: currencyList = ['AUD']
+currencyList = ['EUR', 'XCD', 'USD', 'XOF', 'NOK', 'AUD', 'XAF', 'NZD', 'MAD', 'DKK', 'GBP', 'CHF', 'XPF', 'ILS', 'ROL', 'TRL']
+
Index: branches/features/taskProcedureRework/grails-app/conf/DataSource.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/conf/DataSource.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/conf/DataSource.groovy	(revision 753)
@@ -0,0 +1,83 @@
+dataSource {
+    // Open separate connections to database for every request or pool connections.
+    pooled = true
+}
+hibernate {
+    cache.use_second_level_cache=true
+    cache.use_query_cache=true
+    cache.provider_class='net.sf.ehcache.hibernate.EhCacheProvider'
+}
+
+// dbCreate options.
+// create-drop: Drop and re-create the database tables on restart. Deletes existing data.
+// create:       Create the database if it doesn't exist, but don't modify it if it does. Deletes existing data.
+// update:     Create the database if it doesn't exist, and modify it if it does exist. Keep data.
+// If nothing specified then do nothing to database schema.
+
+// Environment specific settings.
+environments {
+    development {
+        dataSource {
+            /** HSQLDB - In memory */
+            driverClassName = "org.hsqldb.jdbcDriver"
+            username = "sa"
+            password = ""
+            dbCreate = "create-drop"
+            url = "jdbc:hsqldb:mem:devDb"
+            /** MySQL */
+//             driverClassName = "com.mysql.jdbc.Driver"
+//             username = "gnumimsadmin"
+//             password = "gnumimsadmin"
+//             dbCreate = "create-drop"
+//             url = "jdbc:mysql://host:3306/gnumims_dev?autoReconnect=true&sessionVariables=storage_engine=InnoDB"
+        }
+    }
+    test {
+        dataSource {
+            /** HSQLDB - In memory */
+            driverClassName = "org.hsqldb.jdbcDriver"
+            username = "sa"
+            password = ""
+            dbCreate = "update"
+            url = "jdbc:hsqldb:mem:devDb"
+            /** MySQL */
+//             driverClassName = "com.mysql.jdbc.Driver"
+//             username = "gnumimsadmin"
+//             password = "gnumimsadmin"
+//             dbCreate = "update"
+//             url = "jdbc:mysql://host:3306/gnumims_test?autoReconnect=true&sessionVariables=storage_engine=InnoDB"
+        }
+    }
+    production {
+        dataSource {
+            /* Delete dbCreate line after setup! */
+            /** HSQLDB - In memory */
+//             driverClassName = "org.hsqldb.jdbcDriver"
+//             username = "sa"
+//             password = ""
+//             dbCreate = "create-drop"
+//             url = "jdbc:hsqldb:mem:devDb"
+            /** HSQLDB - In file */
+//             driverClassName = "org.hsqldb.jdbcDriver"
+//             username = "sa"
+//             password = ""
+//             dbCreate = "update"
+//             url = "jdbc:hsqldb:file:prodDb;shutdown=true"
+            /** MSSQL */
+            //For more info see the docs that you downloaded with the driver.
+//             dialect = org.hibernate.dialect.SQLServerDialect // Useful with `grails schema-export`
+//             driverClassName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
+//             username = "gnumimsadmin"
+//             password = "gnumimsadmin"
+//             dbCreate = "update"
+//             url = "jdbc:sqlserver://gnumimssql01:1433;databaseName=gnumims_prod"
+            /** MySQL */
+            driverClassName = "com.mysql.jdbc.Driver"
+            username = "gnumimsadmin"
+            password = "gnumimsadmin"
+            dbCreate = "update"
+            url = "jdbc:mysql://gnumimssql01:3306/gnumims_prod?autoReconnect=true&sessionVariables=storage_engine=InnoDB"
+        }
+
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/conf/NoCacheFilters.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/conf/NoCacheFilters.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/conf/NoCacheFilters.groovy	(revision 753)
@@ -0,0 +1,26 @@
+class NoCacheFilters {
+
+    def filters = {
+        all(controller:'*', action:'*') {
+            before = {
+                
+                //Turn off as much caching as we can.
+                response.setHeader("Cache-Control", "no-cache,no-store,must-revalidate")// HTTP 1.1
+                response.addDateHeader('Expires', 0)
+                response.setDateHeader('max-age', 0)
+                response.setIntHeader ('Expires', -1) //prevents caching at the proxy server
+                response.addHeader('cache-Control', 'private') //IE5.x only 
+                response.addHeader('Pragma', 'no-cache') //HTTP 1.0
+
+            }
+
+            after = {
+                
+            }
+            afterView = {
+                
+            }
+        }
+    }
+    
+}
Index: branches/features/taskProcedureRework/grails-app/conf/Searchable.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/conf/Searchable.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/conf/Searchable.groovy	(revision 753)
@@ -0,0 +1,168 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
+/**
+ * This {@link groovy.util.ConfigObject} script provides Grails Searchable Plugin configuration.
+ *
+ * You can use the "environments" section at the end of the file to define per-environment
+ * configuration.
+ *
+ * Note it is NOT required to add a reference to this file in Config.groovy; it is loaded by
+ * the plugin itself.
+ *
+ * Available properties in the binding are:
+ *
+ * @param userHome The current user's home directory.
+ *                 Same as System.properties['user.home']
+ * @param appName The Grails environment (ie, "development", "test", "production").
+ *                Same as System.properties['grails.env']
+ * @param appVersion The version of your application
+ * @param grailsEnv The Grails environment (ie, "development", "test", "production").
+ *                  Same as System.properties['grails.env']
+ *
+ * You can also use System.properties to refer to other JVM properties.
+ *
+ * This file is created by "grails install-searchable-config", and replaces
+ * the previous "SearchableConfiguration.groovy"
+ */
+searchable {
+
+    /**
+    * The location of the Compass index
+    *
+    * Examples: "/home/app/compassindex", "ram://app-index" or null to use the default
+    *
+    * The default is "${user.home}/.grails/projects/${app.name}/searchable-index/${grails.env}"
+    */
+    compassConnection = new File(ConfigurationHolder.config.globalDirs.searchableIndexDirectory).absolutePath
+
+    /**
+     * Any settings you wish to pass to Compass
+     *
+     * Use this to configure custom/override default analyzers, query parsers, eg
+     *
+     *     Map compassSettings = [
+     *         'compass.engine.analyzer.german.type': 'German'
+     *     ]
+     *
+     * gives you an analyzer called "german" you can then use in mappings and queries, like
+     *
+     *    class Book {
+     *        static searchable = { content analyzer: 'german' }
+     *        String content
+     *    }
+     *
+     *    Book.search("unter", analyzer: 'german')
+     *
+     * Documentation for Compass settings is here: http://www.compass-project.org/docs/2.1.0M2/reference/html/core-settings.html
+     */
+    compassSettings = [:]
+
+    /**
+     * Default mapping property exclusions
+     *
+     * No properties matching the given names will be mapped by default
+     * ie, when using "searchable = true"
+     *
+     * This does not apply for classes using "searchable = [only/except: [...]]"
+     * or mapping by closure
+     */
+    defaultExcludedProperties = ["password"]
+
+    /**
+     * Default property formats
+     *
+     * Value is a Map between Class and format string, eg
+     *
+     *     [(Date): "yyyy-MM-dd'T'HH:mm:ss"]
+     *
+     * Only applies to class properties mapped as "searchable properties", which are typically
+     * simple class types that can be represented as Strings (rather than references
+     * or components) AND only required if overriding the built-in format.
+     */
+    defaultFormats = [:]
+
+    /**
+     * Set default options for each SearchableService/Domain-class method, by method name.
+     *
+     * These can be overriden on a per-query basis by passing the method a Map of options
+     * containing those you want to override.
+     *
+     * You may want to customise the options used by the search method, which are:
+     *
+     * @param reload          whether to reload domain class instances from the DB: true|false
+     *                        If true, the search  will be slower but objects will be associated
+     *                        with the current Hibernate session
+     * @param escape          whether to escape special characters in string queries: true|false
+     * @param offset          the 0-based hit offset of the first page of results.
+     *                        Normally you wouldn't change it from 0, it's only here because paging
+     *                        works by using an offset + max combo for a specific page
+     * @param max             the page size, for paged search results
+     * @param defaultOperator if the query does not otherwise indicate, then the default operator
+     *                        applied: "or" or "and".
+     *                        If "and" means all terms are required for a match, if "or" means
+     *                        any term is required for a match
+     * @param suggestQuery    if true and search method is returning a search-result object
+     *                        (rather than a domain class instance, list or count) then a
+     *                        "suggestedQuery" property is also added to the search-result.
+     *                        This can also be a Map of options as supported by the suggestQuery
+     *                        method itself
+     *
+     * For the options supported by other methods, please see the documentation
+     * http://grails.org/Searchable+Plugin
+     */
+    defaultMethodOptions = [
+        search: [reload: false, escape: false, offset: 0, max: 10, defaultOperator: "and"],
+        suggestQuery: [userFriendly: true]
+    ]
+
+    /**
+     * Should changes made through GORM/Hibernate be mirrored to the index
+     * automatically (using Compass::GPS)?
+     *
+     * If false, you must manage the index manually using index/unindex/reindex
+     */
+    mirrorChanges = false
+
+    /**
+     * Should the database be indexed at startup (using Compass:GPS)?
+     *
+     * Possible values: true|false|"fork"
+     *
+     * The value may be a boolean true|false or a string "fork", which means true,
+     * and fork a thread for it
+     *
+     * If you use BootStrap.groovy to insert your data then you should use "true",
+     * which means do a non-forking, otherwise "fork" is recommended
+     */
+    bulkIndexOnStartup = false
+
+    /**
+     * Should index locks be removed (if present) at startup?
+     */
+    releaseLocksOnStartup = true
+}
+
+// per-environment settings
+environments {
+    development {
+        searchable {
+            // development is default; inherits from above
+        }
+    }
+
+    test {
+        searchable {
+            // disable bulk index on startup
+            bulkIndexOnStartup = false
+
+            // use faster in-memory index
+            compassConnection = "ram://test-index"
+        }
+    }
+
+    production {
+        searchable {
+            // add your production settings here
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/conf/SecurityConfig.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/conf/SecurityConfig.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/conf/SecurityConfig.groovy	(revision 753)
@@ -0,0 +1,89 @@
+security {
+
+    def authenticateService
+
+	// See DefaultSecurityConfig.groovy for all settable/overridable properties
+
+	active = true
+
+	loginUserDomainClass = "Person"
+    userName = 'loginName'
+    password = 'password'
+    enabled = 'isActive'
+
+	authorityDomainClass = "Authority"
+
+    // Required if we want to run "grails generate-manager"
+    // Which recreates the controller and views, so save the views!
+//     requestMapClass = 'Requestmap'
+
+    // The whole application relies on controllerAnnotations and the static rules bellow.
+    useRequestMapDomainClass = false
+    useControllerAnnotations = true
+
+    // Set true especially if used across the internet.
+    forceHttps = 'false'
+
+    // Pessimistic locking, deny access to all URLs that don't 
+    // have an applicable URL-Role configuration.
+    // This forces us to set an annotation, static rule or
+    // extend BaseController and prevents accidentally leaving pages open.
+    controllerAnnotationsRejectIfNoRule = true
+
+    // Static rules for controllers, actions and urls.
+    // Since we are using pessimistic locking we have to set some things
+    // here but most security should be set in the controllers.
+    controllerAnnotationStaticRules = [
+    '/': ['IS_AUTHENTICATED_FULLY'],
+    '/index.gsp': ['IS_AUTHENTICATED_FULLY'],
+    '/css/*': ['IS_AUTHENTICATED_ANONYMOUSLY'],
+    '/images/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
+    '/js/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
+    '/plugins/**': ['IS_AUTHENTICATED_FULLY'],
+    '/plugins/*/images/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
+    '/plugins/*/css/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
+    '/plugins/*/js/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
+    '/classDiagram*': ['IS_AUTHENTICATED_FULLY'],
+    '/classDiagram/**': ['IS_AUTHENTICATED_FULLY'],
+    '/login*': ['IS_AUTHENTICATED_ANONYMOUSLY'],
+    '/login/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
+    '/logout*': ['IS_AUTHENTICATED_FULLY'],
+    '/logout/**': ['IS_AUTHENTICATED_FULLY'],
+    '/image*': ['IS_AUTHENTICATED_FULLY'],
+    '/image/**': ['IS_AUTHENTICATED_FULLY'],
+    '/reports*': ['IS_AUTHENTICATED_FULLY'],
+    '/reports/**': ['IS_AUTHENTICATED_FULLY'],
+    '/jasper*': ['IS_AUTHENTICATED_FULLY'],
+    '/jasper/**': ['IS_AUTHENTICATED_FULLY']
+    ]
+
+    // Always call the welcome action so that bookmarks are not used, a
+    // welcome message can be populated and the sessionTimeout can be set.
+    defaultTargetUrl = '/appCore/welcome'
+    alwaysUseDefaultTargetUrl = true
+
+    // User caching, turned this off so that password changes take effect.
+    // It would appear that user is still in the session as logout/login
+    // is still required for role changes to take effect.
+    // If this option causes high database load try:
+    //  import org.acegisecurity.providers.dao.DaoAuthenticationProvider
+    //  import org.acegisecurity.context.SecurityContextHolder
+    //  DaoAuthenticationProvider daoAuthenticationProvider 
+    //  def user = SecurityContextHolder.context.authentication.principal.username 
+    //  daoAuthenticationProvider.userCache.removeUserFromCache(user)
+    //  in logout controller and perhaps on password change and role change.
+    cacheUsers = false
+
+//    // Listen for events and run the closure(s) that follow.
+//    // Unfortunately the session is not available yet so many things can't be done here, use a defaultTargetUrl and controller.
+//    useSecurityEventListener = true
+//
+//    onAuthenticationSuccessEvent = { e, appCtx ->
+//        def p = e.source.principal
+//        def personInstance = Person.findByLoginName(p.username)
+//        println p.username
+//        println personInstance.loginName
+//        println personInstance.firstName
+//    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/conf/UrlMappings.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/conf/UrlMappings.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/conf/UrlMappings.groovy	(revision 753)
@@ -0,0 +1,20 @@
+class UrlMappings {
+    static mappings = {
+        "/$controller/$action?/$id?"{
+            constraints {
+                // apply constraints here
+            }
+        }
+
+        "/image/$id/$size?/$filename?" {
+            constraints {
+                size(matches: /\d+/)
+            }
+            controller = 'pictureDetailed'
+            action = 'view'
+        }
+
+        "/"(view:"/index")
+        "500"(view:'/error')
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/conf/spring/resources.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/conf/spring/resources.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/conf/spring/resources.groovy	(revision 753)
@@ -0,0 +1,4 @@
+// Place your Spring DSL code here
+beans = {
+    
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/AddressDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/AddressDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/AddressDetailedController.groovy	(revision 753)
@@ -0,0 +1,115 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                    'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager'])
+class AddressDetailedController extends BaseController {
+
+    def addressService
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                        'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager', 'ROLE_AppUser'])
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                        'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager', 'ROLE_AppUser'])
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ addressInstanceList: Address.list( params ), addressInstanceTotal: Address.count() ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                        'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager', 'ROLE_AppUser'])
+    def show = {
+        def addressInstance = Address.get( params.id )
+
+        if(!addressInstance) {
+            flash.message = "Address not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ addressInstance : addressInstance ] }
+    }
+
+    def delete = {
+        def addressInstance = Address.get( params.id )
+        if(addressInstance) {
+            try {
+                addressInstance.delete(flush:true)
+                flash.message = "Address ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "Address ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "Address not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def addressInstance = Address.get( params.id )
+
+        if(!addressInstance) {
+            flash.message = "Address not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ addressInstance : addressInstance ]
+        }
+    }
+
+    def update = {
+        def addressInstance = Address.get( params.id )
+        if(addressInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(addressInstance.version > version) {
+
+                    addressInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[addressInstance:addressInstance])
+                    return
+                }
+            }
+            addressInstance.properties = params
+            if(!addressInstance.hasErrors() && addressInstance.save(flush: true)) {
+                flash.message = "Address ${params.id} updated"
+                redirect(action:show,id:addressInstance.id)
+            }
+            else {
+                render(view:'edit',model:[addressInstance:addressInstance])
+            }
+        }
+        else {
+            flash.message = "Address not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def result = addressService.create(params)
+
+        if(!result.error)
+            return [addressInstance: result.addressInstance]
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: list)
+    }
+
+    def save = {
+        def result = addressService.save(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.create.success", args: ["Address", result.addressInstance.id])
+            redirect(action:show, id: result.addressInstance.id)
+            return
+        }
+
+        render(view:'create', model:[addressInstance: result.addressInstance])
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/AppConfigController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/AppConfigController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/AppConfigController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class AppConfigController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ appConfigInstanceList: AppConfig.list( params ), appConfigInstanceTotal: AppConfig.count() ]
+    }
+
+    def show = {
+        def appConfigInstance = AppConfig.get( params.id )
+
+        if(!appConfigInstance) {
+            flash.message = "AppConfig not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ appConfigInstance : appConfigInstance ] }
+    }
+
+    def delete = {
+        def appConfigInstance = AppConfig.get( params.id )
+        if(appConfigInstance) {
+            try {
+                appConfigInstance.delete(flush:true)
+                flash.message = "AppConfig ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "AppConfig ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "AppConfig not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def appConfigInstance = AppConfig.get( params.id )
+
+        if(!appConfigInstance) {
+            flash.message = "AppConfig not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ appConfigInstance : appConfigInstance ]
+        }
+    }
+
+    def update = {
+        def appConfigInstance = AppConfig.get( params.id )
+        if(appConfigInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(appConfigInstance.version > version) {
+                    
+                    appConfigInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[appConfigInstance:appConfigInstance])
+                    return
+                }
+            }
+            appConfigInstance.properties = params
+            if(!appConfigInstance.hasErrors() && appConfigInstance.save(flush: true)) {
+                flash.message = "AppConfig ${params.id} updated"
+                redirect(action:show,id:appConfigInstance.id)
+            }
+            else {
+                render(view:'edit',model:[appConfigInstance:appConfigInstance])
+            }
+        }
+        else {
+            flash.message = "AppConfig not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def appConfigInstance = new AppConfig()
+        appConfigInstance.properties = params
+        return ['appConfigInstance':appConfigInstance]
+    }
+
+    def save = {
+        def appConfigInstance = new AppConfig(params)
+        if(!appConfigInstance.hasErrors() && appConfigInstance.save(flush: true)) {
+            flash.message = "AppConfig ${appConfigInstance.id} created"
+            redirect(action:show,id:appConfigInstance.id)
+        }
+        else {
+            render(view:'create',model:[appConfigInstance:appConfigInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/AppCoreController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/AppCoreController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/AppCoreController.groovy	(revision 753)
@@ -0,0 +1,321 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+import org.codehaus.groovy.grails.commons.*
+import org.apache.commons.lang.WordUtils
+
+/**
+* Controller class for the application core views.
+*/
+class AppCoreController extends BaseController {
+
+    def authService
+    def assetService
+    def appConfigService
+    def createDataService
+    def searchableService
+    def assetSubItemService
+    def createBulkDataService
+
+    def index = { redirect(action:start,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    //def allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    /**
+    * This is where we arrive after login.
+    *  Attach the welcome flash message and redirect to where ever we want the user to start.
+    * e.g. redirect(controller:"taskDetailed", action:"search")
+    */
+    def welcome = {
+        def personInstance = authService.currentUser
+        flash.message = "Welcome, ${personInstance.firstName} ${personInstance.lastName}."
+
+        def sess = getSession()
+        sess.setMaxInactiveInterval(personInstance.sessionTimeout)
+        redirect(action:start)
+    }
+
+    /**
+    * Render the start view.
+    */
+    def start = {
+        def grailsVersion = grailsApplication.metadata['app.grails.version']
+        def applicationVersion = grailsApplication.metadata['app.version']
+        def applicationName = grailsApplication.metadata['app.name']
+        def applicationVcsRevision = grailsApplication.metadata['app.vcsRevision']
+
+        // Build the application string.
+        def applicationString = WordUtils.capitalize(applicationName)
+        if(applicationVersion)
+            applicationString += "-" + applicationVersion
+        if(applicationVcsRevision) {
+            if(applicationVcsRevision.size() > 7)  { // Svn's $Rev: NUM $
+                applicationVcsRevision = applicationVcsRevision[6..-3]
+                applicationString += " (rev " + applicationVcsRevision + ")"
+            }
+            else
+                applicationString += " (" + applicationVcsRevision + ")"
+        }
+
+        // Build the plugins string.
+        def pluginProperties = grailsApplication.metadata.findAll {it.key.contains('plugin')}
+        pluginProperties.each() {
+            it.key = WordUtils.capitalize( (it.key + GString.EMPTY).split("\\.")[-1] )
+        }
+        pluginProperties = pluginProperties.sort { p1, p2 -> p1.key.compareToIgnoreCase(p2.key) }
+        def plugins = pluginProperties.collect{ it.key + '-' + it.value }.join(", ")
+
+        def sections = Section.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+
+        def showTab = [:]
+        switch (params.showTab) {
+            case "showReportsTab":
+                showTab.reports =  new String("true")
+                break
+            case "showOptionsTab":
+                showTab.Options =  new String("true")
+                break
+            case "showAboutTab":
+                showTab.about =  new String("true")
+                break
+            default:
+                showTab.quickLinks = new String("true")
+        }
+
+        return [grailsVersion: grailsVersion,
+                    applicationString: applicationString,
+                    plugins: plugins,
+                    sections: sections,
+                    showTab: showTab]
+    }
+
+    /**
+    * Allow a person to change their session timeout setting.
+    */
+    def changeSessionTimeout = {
+        if (request.method == 'GET') {
+            def personInstance = authService.currentUser
+            return [ personInstance : personInstance ]       
+        }
+        if (request.method == 'POST') {
+            def personInstance = authService.currentUser
+                personInstance.properties = params
+                if (!personInstance.hasErrors() && personInstance.save(flush: true)) {
+                    def sess = getSession()
+                    sess.setMaxInactiveInterval(personInstance.sessionTimeout)
+                    flash.message = "Session timeout changed."
+                    redirect(action:start)
+                }
+                else {
+                    render(view:'changeSessionTimeout',model:[personInstance:personInstance])
+                }
+        }
+    }
+
+    /**
+    * Allow a person to change their password.
+    */
+    def changePassword = {
+        //def principal = authenticateService.principal()
+        //log.info principal.getAuthorities()
+
+        if (request.method == 'GET') {
+            def personInstance = authService.currentUser
+            return [ personInstance : personInstance ]       
+        }
+
+        if (request.method == 'POST') {
+            def personInstance = authService.currentUser
+
+            if(params.confirmPass == params.pass) {
+                personInstance.pass = params.pass
+                personInstance.password = authService.encodePassword(personInstance.pass)
+
+                if (!personInstance.hasErrors() && personInstance.save(flush: true)) {
+                    //userCache.removeUserFromCache(personInstance.loginName)
+                    flash.message = "Password changed successfully."
+                    redirect(action:start)
+                }
+                else {
+                    render(view:'changePassword',model:[personInstance:personInstance])
+                }
+            }
+            else {
+                personInstance.errors.reject('person.pass.doesNotMatch',            // Error code, see grails-app/i18n/message.properties
+                                                                ['pass', 'class Person'].toArray(),      // Groovy ListArray cast to Object[]
+                                                                 '[NothingUseMessageProperites]')  // Default mapping string.
+                render(view:'changePassword',model:[personInstance:personInstance])
+            }
+
+        }
+    }
+
+    /**
+    * Render the manager view for manager or admin roles.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                        'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager'])
+    def manager = {
+    }
+
+    /**
+    * Render the appAdmin view for admin roles.
+    */
+    @Secured(['ROLE_AppAdmin'])
+    def appAdmin = {
+
+        def offerBaseDataCreation = false
+        def offerDemoDataCreation = false
+        def baseDataCreated = appConfigService.exists("baseDataCreated")
+        def demoDataCreated = appConfigService.exists("demoDataCreated")
+        def demoDataCreationDisabled = appConfigService.exists("demoDataCreationDisabled")
+
+        if(!baseDataCreated)
+            offerBaseDataCreation = true
+
+        if(baseDataCreated && !demoDataCreated && !demoDataCreationDisabled)
+            offerDemoDataCreation = true
+
+        return[baseDataCreated: baseDataCreated,
+                        demoDataCreated: demoDataCreated,
+                        offerDemoDataCreation: offerDemoDataCreation,
+                        offerBaseDataCreation: offerBaseDataCreation,
+                        demoDataCreationDisabled: demoDataCreationDisabled]
+    }
+
+    /**
+    * Allow admin to disable demo data creation.
+    */
+    @Secured(['ROLE_AppAdmin'])
+    def disableDemoDataCreation = {
+        if(!appConfigService.set("demoDataCreationDisabled")) {
+            flash.message = "Demo data creation could not be disabled."
+            redirect(action: appAdmin)
+            return
+        }
+
+        // Success.
+        flash.message = "Demo data creation disabled."
+        redirect(action: appAdmin)
+    }
+
+    /**
+    * Allow admin to create base data.
+    */
+    @Secured(['ROLE_AppAdmin'])
+    def createBaseData = {
+        if(!createDataService.createBaseData()) {
+            flash.message = "Base data could not be created."
+            redirect(action: appAdmin)
+            return
+        }
+
+        // Success.
+        flash.message = "Base data created."
+        redirect(action: appAdmin)
+    }
+
+    /**
+    * Allow admin to create demo data.
+    */
+    @Secured(['ROLE_AppAdmin'])
+    def createDemoData = {
+        if(!createDataService.createDemoData()) {
+            flash.message = "Demo data could not be created."
+            redirect(action: appAdmin)
+            return
+        }
+
+        // Success.
+        flash.message = "Demo data created."
+        redirect(action: appAdmin)
+    }
+
+    /**
+    * Allow admin to create bulk test data.
+    */
+    @Secured(['ROLE_AppAdmin'])
+    def createBulkTestData = {
+        def result = createBulkDataService.createAll()
+        if(!result.error) {
+            flash.message = g.message(code:"default.create.success", args:["Bulk test data", ''])
+            redirect(action: appAdmin)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: appAdmin)
+    }
+
+    /**
+    * Allow admin to create bulk inventory test data.
+    */
+    @Secured(['ROLE_AppAdmin'])
+    def createBulkInventoryTestData = {
+        def result = createBulkDataService.createBulkInventoryTestData()
+        if(!result.error) {
+            flash.message = g.message(code:"default.create.success", args:["Bulk test data", ''])
+            redirect(action: appAdmin)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: appAdmin)
+    }
+
+    /**
+    * Render the application log file.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                        'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager'])
+    def appLog = {
+        def file = new File(ConfigurationHolder.config.log4j.appenders.appLog.file)
+
+        // Success.
+        [log: file.text]
+    }
+
+    /**
+    * Rebuild the text search index.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                        'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager'])
+    def rebuildTextSearchIndex = {
+        InventoryIndexJob.triggerNow(['calledBy':'AppCoreController rebuildTextSearchIndex{}'])
+
+        flash.message = g.message(code:"appCore.rebuild.text.search.index")
+        redirect(action: manager)
+    }
+
+    /**
+    * Allow admin to create recommended extended attributes for assets.
+    */
+    @Secured(['ROLE_AppAdmin'])
+    def createRecommendedAssetExtendedAttributes = {
+        def result = assetService.createRecommendedExtendedAttributes()
+        if(!result.error) {
+            flash.message = g.message(code:"default.create.success", args:["Extended attributes created", ''])
+            redirect(action: appAdmin)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: appAdmin)
+    }
+
+    /**
+    * Allow admin to create recommended extended attributes for level 1 assetSubItems.
+    */
+    @Secured(['ROLE_AppAdmin'])
+    def createRecommendedAssetSubItemExtendedAttributes = {
+        def result = assetSubItemService.createRecommendedExtendedAttributes()
+        if(!result.error) {
+            flash.message = g.message(code:"default.create.success", args:["Extended attributes created", ''])
+            redirect(action: appAdmin)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: appAdmin)
+    }
+
+} // end of class.
Index: branches/features/taskProcedureRework/grails-app/controllers/AssetDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/AssetDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/AssetDetailedController.groovy	(revision 753)
@@ -0,0 +1,399 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+import org.apache.commons.lang.WordUtils
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class AssetDetailedController extends BaseController {
+
+    def assetCsvService
+    def filterService
+    def exportService
+    def assetService
+    def assetTreeService
+    def taskService
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST', saveCopy:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def index = { redirect(action:search,params:params) }
+
+    /**
+    * Set session.assetSearchParamsMax
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def setSearchParamsMax = {
+        def max = 1000
+        if(params.newMax?.isInteger()) {
+            def i = params.newMax.toInteger()
+            if(i > 0 && i <= max)
+                session.assetSearchParamsMax = params.newMax
+            if(i > max)
+                session.assetSearchParamsMax = max
+        }
+        forward(action: 'search', params: params)
+    }
+
+    /**
+    * Build and return the asset tree response for the AJAX request.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def assetTree = {
+        def s = assetTreeService.buildAssetTree(params, session)
+        render s
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def exportAssetTreeHtml = {
+        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
+        response.setHeader("Content-disposition", "attachment; filename=AssetTree.html")
+        def s = assetTreeService.buildAssetTree(params, session)
+        render s
+    }
+
+    /**
+    * Save the asset tree status in the current http session.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def saveAssetTreeStatus = {
+        session.assetTreeVisibleBranches = params.assetTreeVisibleBranches
+    }
+
+    /**
+    * Disaply the import view.
+    */
+    def importAssetTree = {
+    }
+
+    /**
+    * Handle the import save.
+    */
+    def importAssetTreeSave = {
+        def result = assetCsvService.importAssetTree(request)
+
+        if(!result.error) {
+            flash.message = g.message(code: "asset.tree.import.success")
+            redirect(action:search)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: importAssetTree)
+    }
+
+    /**
+    * Export a csv template.
+    * NOTE: IE has a 'validating' bug in dev mode that causes the export to take a long time!
+    * This does not appear to be a problem once deployed to Tomcat.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def exportAssetTreeTemplate = {
+        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
+        response.setHeader("Content-disposition", "attachment; filename=AssetTreeTemplate.csv")
+        def s = assetCsvService.buildAssetTreeTemplate()
+        render s
+    }
+
+    /**
+    * Export a csv test file.
+    */
+    def exportAssetTreeTest = {
+        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
+        response.setHeader("Content-disposition", "attachment; filename=AssetTreeTestFile.csv")
+        def s = assetCsvService.buildAssetTreeTest()
+        render s
+    }
+
+    /**
+    * Export the entire asset tree as a csv file.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def exportAssetTree = {
+
+        def assetList = Asset.list()
+
+        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
+        response.setHeader("Content-disposition", "attachment; filename=AssetTree.csv")
+        def s = assetCsvService.buildAssetTree(assetList)
+        render s
+    }
+
+    /**
+    * Search action.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def search = {
+
+        if(session.assetSearchParamsMax)
+            params.max = session.assetSearchParamsMax
+
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  1000)
+
+        def assetInstanceList = []
+        def assetInstanceTotal
+        def filterParams = [:]
+
+        // Quick Search:
+        if(!params.filter) {
+            assetInstanceList = Asset.list( params )
+            assetInstanceTotal = Asset.count()
+            filterParams.quickSearch = params.quickSearch
+        }
+        else {
+        // filterPane:
+            assetInstanceList = filterService.filter( params, Asset )
+            assetInstanceTotal = filterService.count( params, Asset )
+            filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
+        }
+
+        // export plugin:
+        if(params?.format && params.format != "html") {
+
+            def dateFmt = { date ->
+                formatDate(format: "EEE, dd-MMM-yyyy", date: date)
+            }
+
+//             def fmtAsset = { m ->
+//                     def r = ''
+//                     def assetInstance = Asset.findByName(m)
+// 
+//                     r +=  assetInstance
+//                     r += ", "
+// 
+//                     def  lastSubAsset = assetInstance.subAssets.size() - 1
+//                     assetInstance.subAssets.eachWithIndex() { obj, i ->
+//                         r += "\"" + obj + "\""
+//                         if( i < lastSubAsset )
+//                             r += ", "
+//                     }
+//                     return r
+//             }
+
+//             def fmtSubAsset = { m ->
+//                     def r = ''
+//                     m.each() {
+//                         def machine = Machine.findByName(it)
+//                         def assemblies = machine.assemblies
+//                         r += machine.name
+//                         r += " "
+//                         r += assemblies
+//                         r += " "
+//                     }
+//                     return r
+//             }
+
+            String title = "Asset List."
+
+            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
+            response.setHeader("Content-disposition", "attachment; filename=Assets.${params.extension}")
+            List fields = ["section.site",
+                                "section",
+                                "name",
+                                "description"]
+            Map labels = ["section.site": "Site",
+                                "section": "Section",
+                                "name": "Asset",
+                                "description": "Description"]
+//             Map labels
+//             Map formatters = ["subAsset.name": fmtSubAsset]
+            Map formatters = [:]
+            Map parameters = [title: title, separator: ","]
+
+            exportService.export(params.format,
+                                                response.outputStream,
+                                                assetInstanceList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) },
+                                                fields,
+                                                labels,
+                                                formatters,
+                                                parameters)
+        }
+
+        // Add some basic params to filterParams.
+        filterParams.max = params.max
+        filterParams.offset = params.offset?.toInteger() ?: 0
+        filterParams.sort = params.sort ?: "id"
+        filterParams.order = params.order ?: "desc"
+
+        return[ assetInstanceList: assetInstanceList,
+                assetInstanceTotal: assetInstanceTotal,
+                filterParams: filterParams ]
+
+    } // end search()
+
+    /**
+    * Show action.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def assetInstance = Asset.get( params.id )
+
+        if(!assetInstance) {
+            flash.message = "Asset not found with id ${params.id}"
+            redirect(action:search)
+            return
+        }
+
+        return [ assetInstance : assetInstance,
+                        parentPMs: taskService.getParentPMs(assetInstance)]
+    }
+
+    /**
+    * Delete action.
+    */
+    def delete = {
+        def result = assetService.delete(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.delete.success", args: ["Asset", params.id])
+            redirect(action:search)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.error.code == "default.not.found") {
+            redirect(action:search)
+            return
+        }
+
+        redirect(action:show, id: params.id)
+    }
+
+    /**
+    * Edit action.
+    */
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def assetInstance = Asset.get( params.id )
+
+        if(!assetInstance) {
+            flash.message = "Asset not found with id ${params.id}"
+            redirect(action:search)
+            return
+        }
+
+        return [ assetInstance : assetInstance,
+                        possibleAssetSubItems: assetService.possibleAssetSubItems(),
+                        parentPMs: taskService.getParentPMs(assetInstance) ]
+
+    }
+
+    /**
+    * Update action.
+    */
+    def update = {
+        def assetInstance = Asset.get( params.id )
+
+        if(!assetInstance) {
+            flash.message = "Asset not found with id ${params.id}"
+            redirect(action:search)
+            return
+        }
+
+        if(params.version) {
+            def version = params.version.toLong()
+            if(assetInstance.version > version) {
+
+                assetInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                render(view:'edit',model:[assetInstance:assetInstance,
+                                                            possibleAssetSubItems: assetService.possibleAssetSubItems(),
+                                                            parentPMs: taskService.getParentPMs(assetInstance)] )
+                return
+            }
+        }
+
+        assetInstance.properties = params
+
+        use(WordUtils) {
+            assetInstance.name = assetInstance.name.capitalize()
+            assetInstance.description = assetInstance.description.capitalize()
+        }
+
+        assetInstance.setAssetSubItemsFromCheckBoxList(params.assetSubItems)
+
+        if(!assetInstance.hasErrors() && assetInstance.save(flush: true)) {
+            flash.message = "Asset '${assetInstance.name}' updated"
+            redirect(action:show,id:assetInstance.id)
+        }
+        else {
+            render(view:'edit',model:[assetInstance:assetInstance,
+                                                        possibleAssetSubItems: assetService.possibleAssetSubItems(),
+                                                        parentPMs: taskService.getParentPMs(assetInstance)] )
+        }
+
+    }
+
+    /**
+    * Create action.
+    */
+    def create = {
+        def result = assetService.create(params)
+
+        if(!result.error)
+            return [assetInstance: result.assetInstance]
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: search)
+    }
+
+    /**
+    * Copy action.
+    */
+    def copy = {
+        def result = assetService.copy(params)
+
+        if(!result.error)
+            return [assetInstance: result.assetInstance, assetToCopy: result.assetToCopy]
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: search)
+    }
+
+    /**
+    * Save action.
+    */
+    def save = {
+        def result = assetService.save(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.create.success", args: ["Asset",  "'${result.assetInstance.name}'"])
+            redirect(action:show, id: result.assetInstance.id)
+            return
+        }
+
+        render(view:'create', model:[assetInstance: result.assetInstance])
+    }
+
+    /**
+    * Copy save action.
+    */
+    def saveCopy = {
+        def result = assetService.saveCopy(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.create.success", args: ["Asset", result.assetInstance.id])
+            redirect(action:show, id: result.assetInstance.id)
+            return
+        }
+
+        if(result.error.code == "default.not.found") {
+            flash.message = g.message(code: result.error.code, args: ["Asset", params.assetToCopy?.id])
+            redirect(action: search)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: ["Asset"])
+
+        render(view:'copy', model:[assetInstance: result.assetInstance, assetToCopy: result.assetToCopy])
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/controllers/AssetExtendedAttributeDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/AssetExtendedAttributeDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/AssetExtendedAttributeDetailedController.groovy	(revision 753)
@@ -0,0 +1,97 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class AssetExtendedAttributeDetailedController extends BaseController {
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def index = { redirect(controller: "assetDetailed", action: "search", params:params) }
+
+    def show = {
+        def assetExtendedAttributeInstance = AssetExtendedAttribute.get( params.id )
+
+        if(!assetExtendedAttributeInstance) {
+            flash.message = "AssetExtendedAttribute not found with id ${params.id}"
+            redirect(controller: "assetDetailed", action: "search")
+        }
+        else { return [ assetExtendedAttributeInstance : assetExtendedAttributeInstance ] }
+    }
+
+    def delete = {
+        def assetExtendedAttributeInstance = AssetExtendedAttribute.get( params.id )
+        if(assetExtendedAttributeInstance) {
+            def asset = assetExtendedAttributeInstance.asset
+            try {
+                assetExtendedAttributeInstance.delete(flush:true)
+                flash.message = "AssetExtendedAttribute ${params.id} deleted"
+                redirect(controller: "assetDetailed", action: 'show', id: asset.id)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "AssetExtendedAttribute ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "AssetExtendedAttribute not found with id ${params.id}"
+            redirect(controller: "assetDetailed", action: "search")
+        }
+    }
+
+    def edit = {
+        def assetExtendedAttributeInstance = AssetExtendedAttribute.get( params.id )
+
+        if(!assetExtendedAttributeInstance) {
+            flash.message = "AssetExtendedAttribute not found with id ${params.id}"
+            redirect(controller: "assetDetailed", action: "search")
+        }
+        else {
+            return [ assetExtendedAttributeInstance : assetExtendedAttributeInstance ]
+        }
+    }
+
+    def update = {
+        def assetExtendedAttributeInstance = AssetExtendedAttribute.get( params.id )
+        if(assetExtendedAttributeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(assetExtendedAttributeInstance.version > version) {
+                    
+                    assetExtendedAttributeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[assetExtendedAttributeInstance:assetExtendedAttributeInstance])
+                    return
+                }
+            }
+            assetExtendedAttributeInstance.properties = params
+            if(!assetExtendedAttributeInstance.hasErrors() && assetExtendedAttributeInstance.save(flush: true)) {
+                flash.message = "AssetExtendedAttribute ${params.id} updated"
+                //redirect(action:show,id:assetExtendedAttributeInstance.id)
+                redirect(controller: 'assetDetailed', action: 'show', id: assetExtendedAttributeInstance.asset.id)
+            }
+            else {
+                render(view:'edit',model:[assetExtendedAttributeInstance:assetExtendedAttributeInstance])
+            }
+        }
+        else {
+            flash.message = "AssetExtendedAttribute not found with id ${params.id}"
+            redirect(controller: "assetDetailed", action: "search")
+        }
+    }
+
+    def create = {
+        def assetExtendedAttributeInstance = new AssetExtendedAttribute()
+        assetExtendedAttributeInstance.properties = params
+        return ['assetExtendedAttributeInstance':assetExtendedAttributeInstance]
+    }
+
+    def save = {
+        def assetExtendedAttributeInstance = new AssetExtendedAttribute(params)
+        if(!assetExtendedAttributeInstance.hasErrors() && assetExtendedAttributeInstance.save(flush: true)) {
+            flash.message = "AssetExtendedAttribute ${assetExtendedAttributeInstance.id} created"
+            redirect(controller:'assetDetailed', action:'edit',id:assetExtendedAttributeInstance.asset.id)
+        }
+        else {
+            render(view:'create',model:[assetExtendedAttributeInstance:assetExtendedAttributeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/AssetSubItemDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/AssetSubItemDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/AssetSubItemDetailedController.groovy	(revision 753)
@@ -0,0 +1,237 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+import org.apache.commons.lang.WordUtils
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class AssetSubItemDetailedController extends BaseController {
+
+    def filterService
+    def exportService
+    def assetSubItemService
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def index = { redirect(action:search,params:params) }
+
+    /**
+    * Set session.assetSubItemSearchParamsMax
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def setSearchParamsMax = {
+        def max = 1000
+        if(params.newMax?.isInteger()) {
+            def i = params.newMax.toInteger()
+            if(i > 0 && i <= max)
+                session.assetSubItemSearchParamsMax = params.newMax
+            if(i > max)
+                session.assetSubItemSearchParamsMax = max
+        }
+        forward(action: 'search', params: params)
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def search = {
+
+        if(session.assetSubItemSearchParamsMax)
+            params.max = session.assetSubItemSearchParamsMax
+
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  1000)
+
+        def assetSubItemInstanceList = []
+        def assetSubItemInstanceTotal
+        def filterParams = [:]
+
+        // Quick Search:
+        if(!params.filter) {
+            assetSubItemInstanceList = AssetSubItem.list( params )
+            assetSubItemInstanceTotal = AssetSubItem.count()
+            filterParams.quickSearch = params.quickSearch
+        }
+        else {
+        // filterPane:
+            assetSubItemInstanceList = filterService.filter( params, AssetSubItem )
+            assetSubItemInstanceTotal = filterService.count( params, AssetSubItem )
+            filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
+        }
+
+        // export plugin:
+        if(params?.format && params.format != "html") {
+
+            def dateFmt = { date ->
+                formatDate(format: "EEE, dd-MMM-yyyy", date: date)
+            }
+
+            String title = "AssetSubItem List."
+
+            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
+            response.setHeader("Content-disposition", "attachment; filename=assets.${params.extension}")
+            List fields = ["name",
+                                "description"]
+            Map labels = ["name": "AssetSubItem",
+                                "description": "Description"]
+
+            Map formatters = [:]
+            Map parameters = [title: title, separator: ","]
+
+            exportService.export(params.format,
+                                                response.outputStream,
+                                                assetSubItemInstanceList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) },
+                                                fields,
+                                                labels,
+                                                formatters,
+                                                parameters)
+        }
+
+        // Add some basic params to filterParams.
+        filterParams.max = params.max
+        filterParams.offset = params.offset?.toInteger() ?: 0
+        filterParams.sort = params.sort ?: "id"
+        filterParams.order = params.order ?: "desc"
+
+        return[ assetSubItemInstanceList: assetSubItemInstanceList,
+                assetSubItemInstanceTotal: assetSubItemInstanceTotal,
+                filterParams: filterParams ]
+
+    } // end search()
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def assetSubItemInstance = AssetSubItem.get( params.id )
+
+        if(!assetSubItemInstance) {
+            flash.message = "AssetSubItem not found with id ${params.id}"
+            redirect(action: "search")
+        }
+        else { return [ assetSubItemInstance : assetSubItemInstance ] }
+    }
+
+    def delete = {
+        def result = assetSubItemService.delete(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.delete.success", args: ["AssetSubItem", params.id])
+            redirect(action: search)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.error.code == "default.not.found") {
+            redirect(action: search)
+            return
+        }
+
+        redirect(action:show, id: params.id)
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def assetSubItemInstance = AssetSubItem.get( params.id )
+
+        if(!assetSubItemInstance) {
+            flash.message = "AssetSubItem not found with id ${params.id}"
+            redirect(action: "search")
+            return
+        }
+
+        def possibleParentItems = assetSubItemService.possibleParentItems(assetSubItemInstance)
+
+        return [ assetSubItemInstance : assetSubItemInstance, possibleParentItems: possibleParentItems ]
+    }
+
+    def update = {
+        def assetSubItemInstance = AssetSubItem.get( params.id )
+        if(assetSubItemInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(assetSubItemInstance.version > version) {
+
+                    assetSubItemInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[assetSubItemInstance:assetSubItemInstance])
+                    return
+                }
+            }
+
+            assetSubItemInstance.properties = params
+
+            use(WordUtils) {
+                assetSubItemInstance.name = assetSubItemInstance.name.capitalize()
+                assetSubItemInstance.description = assetSubItemInstance.description.capitalize()
+            }
+
+            if(assetSubItemInstance.assets) {
+                assetSubItemInstance.parentItem = null
+            }
+
+            if(!assetSubItemInstance.hasErrors() && assetSubItemInstance.save(flush: true)) {
+                flash.message = "Sub Item '${assetSubItemInstance.name}' updated"
+                redirect(action:"show", id: assetSubItemInstance.id)
+            }
+            else {
+                render(view:'edit',model:[assetSubItemInstance:assetSubItemInstance])
+            }
+        }
+        else {
+            flash.message = "AssetSubItem not found with id ${params.id}"
+            redirect(action: "search")
+        }
+    } // update
+
+    def create = {
+        def result = assetSubItemService.create(params)
+
+        if(!result.error)
+            return [assetSubItemInstance: result.assetSubItemInstance, assetInstance: result.assetInstance]
+
+        flash.message = g.message(code: result.error.code, args: result.error.args)
+        redirect(controller: 'assetDetailed', action: 'search')
+    }
+
+    def save = {
+        def result = assetSubItemService.save(params)
+
+        if(!result.error) {
+            // Success.
+            flash.message = g.message(code: "default.create.success", args: ["Sub Item", "'${result.assetSubItemInstance.name}'"])
+
+            /// @todo: This just grabs the first parent in an unsorted list and needs improving.
+            if(result.assetSubItemInstance.assets)
+                redirect(controller: "assetDetailed", action:"show", id: result.assetSubItemInstance.assets.toArray()[0].id)
+            else {
+                //Get the top parentItem.
+                def parentItem = result.assetSubItemInstance.parentItem
+                def i = 0
+                while(parentItem?.parentItem) {
+                    parentItem = parentItem.parentItem
+                    // Protect against infinite recurrsion.
+                    i++
+                    if(i > 100)
+                        break
+                }
+
+                if(parentItem?.assets)
+                    redirect(controller: "assetDetailed", action:"show", id: parentItem.assets.toArray()[0].id)
+                else
+                    redirect(action:"show", id: result.assetSubItemInstance.id) // End stop if all else fails.
+            }
+            return
+        }
+
+        if(result.error.code == "assetSubItem.asset.not.found")
+            flash.errorMessage = g.message(code: "default.create.success")
+
+        render(view:'create', model:[assetSubItemInstance: result.assetSubItemInstance, assetInstance: result.assetInstance])
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/controllers/AssetSubItemExtendedAttributeDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/AssetSubItemExtendedAttributeDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/AssetSubItemExtendedAttributeDetailedController.groovy	(revision 753)
@@ -0,0 +1,97 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class AssetSubItemExtendedAttributeDetailedController extends BaseController {
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def index = { redirect(controller: "assetDetailed", action: "search", params:params) }
+
+    def show = {
+        def assetSubItemExtendedAttributeInstance = AssetSubItemExtendedAttribute.get( params.id )
+
+        if(!assetSubItemExtendedAttributeInstance) {
+            flash.message = "AssetSubItemExtendedAttribute not found with id ${params.id}"
+            redirect(controller: "assetDetailed", action: "search")
+        }
+        else { return [ assetSubItemExtendedAttributeInstance : assetSubItemExtendedAttributeInstance ] }
+    }
+
+    def delete = {
+        def assetSubItemExtendedAttributeInstance = AssetSubItemExtendedAttribute.get( params.id )
+        if(assetSubItemExtendedAttributeInstance) {
+            def assetSubItem = assetSubItemExtendedAttributeInstance.assetSubItem
+            try {
+                assetSubItemExtendedAttributeInstance.delete(flush:true)
+                flash.message = "AssetSubItemExtendedAttribute ${params.id} deleted"
+                redirect(controller: "assetSubItemDetailed", action: 'show', id: assetSubItem.id)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "AssetSubItemExtendedAttribute ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "AssetSubItemExtendedAttribute not found with id ${params.id}"
+            redirect(controller: "assetDetailed", action: "search")
+        }
+    }
+
+    def edit = {
+        def assetSubItemExtendedAttributeInstance = AssetSubItemExtendedAttribute.get( params.id )
+
+        if(!assetSubItemExtendedAttributeInstance) {
+            flash.message = "AssetSubItemExtendedAttribute not found with id ${params.id}"
+            redirect(controller: "assetDetailed", action: "search")
+        }
+        else {
+            return [ assetSubItemExtendedAttributeInstance : assetSubItemExtendedAttributeInstance ]
+        }
+    }
+
+    def update = {
+        def assetSubItemExtendedAttributeInstance = AssetSubItemExtendedAttribute.get( params.id )
+        if(assetSubItemExtendedAttributeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(assetSubItemExtendedAttributeInstance.version > version) {
+                    
+                    assetSubItemExtendedAttributeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[assetSubItemExtendedAttributeInstance:assetSubItemExtendedAttributeInstance])
+                    return
+                }
+            }
+            assetSubItemExtendedAttributeInstance.properties = params
+            if(!assetSubItemExtendedAttributeInstance.hasErrors() && assetSubItemExtendedAttributeInstance.save(flush: true)) {
+                flash.message = "AssetSubItemExtendedAttribute ${params.id} updated"
+                //redirect(action:show,id:assetSubItemExtendedAttributeInstance.id)
+                redirect(controller: 'assetSubItemDetailed', action: 'show', id: assetSubItemExtendedAttributeInstance.assetSubItem.id)
+            }
+            else {
+                render(view:'edit',model:[assetSubItemExtendedAttributeInstance:assetSubItemExtendedAttributeInstance])
+            }
+        }
+        else {
+            flash.message = "AssetSubItemExtendedAttribute not found with id ${params.id}"
+            redirect(controller: "assetDetailed", action: "search")
+        }
+    }
+
+    def create = {
+        def assetSubItemExtendedAttributeInstance = new AssetSubItemExtendedAttribute()
+        assetSubItemExtendedAttributeInstance.properties = params
+        return ['assetSubItemExtendedAttributeInstance':assetSubItemExtendedAttributeInstance]
+    }
+
+    def save = {
+        def assetSubItemExtendedAttributeInstance = new AssetSubItemExtendedAttribute(params)
+        if(!assetSubItemExtendedAttributeInstance.hasErrors() && assetSubItemExtendedAttributeInstance.save(flush: true)) {
+            flash.message = "AssetSubItemExtendedAttribute ${assetSubItemExtendedAttributeInstance.id} created"
+            redirect(controller:'assetSubItemDetailed', action:'edit',id:assetSubItemExtendedAttributeInstance.assetSubItem.id)
+        }
+        else {
+            render(view:'create',model:[assetSubItemExtendedAttributeInstance:assetSubItemExtendedAttributeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/AssignedGroupDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/AssignedGroupDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/AssignedGroupDetailedController.groovy	(revision 753)
@@ -0,0 +1,130 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager'])
+class AssignedGroupDetailedController extends BaseController {
+
+    def assignedGroupService
+
+    def index = {
+        flash.message = g.message(code: "assignedGroup.task.not.found")
+        redirect(controller:"taskDetailed", action:"search")
+    }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def delete = {
+        def result = assignedGroupService.delete(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.delete.success", args: ["AssignedGroup", params.id])
+            redirect(controller:"taskDetailed", action:"show", id: params.task?.id)
+            return
+        }
+
+        flash.message = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.error.code == "default.not.found") {
+            redirect(controller:"taskDetailed", action:"show", id: params.task?.id)
+            return
+        }
+
+        redirect(action:show, id: params.id)
+    }
+
+    def edit = {
+        def result = assignedGroupService.edit(params)
+
+        if(!result.error) {
+            return [assignedGroupInstance: result.assignedGroupInstance,
+                            personGroup: result.personGroup,
+                            personsInGroup: result.personsInGroup]
+        }
+
+        flash.message = g.message(code: result.error.code, args: result.error.args)
+
+        redirect(controller:"taskDetailed", action:"show", id: params.task?.id)
+
+    }
+
+    def update = {
+        def result = assignedGroupService.update(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.update.success", args: ["AssignedGroup", params.id])
+            redirect(controller:"taskDetailed", action:"show", id: result.assignedGroupInstance.task.id)
+            return
+        }
+
+        if(result.error.code == "default.not.found") {
+            flash.message = g.message(code: result.error.code, args: result.error.args)
+            redirect(controller:"taskDetailed", action:"show", id: params.task?.id)
+            return
+        }
+
+        if(result.error.code == "personGroup.not.found") {
+            flash.message = g.message(code: result.error.code, args: result.error.args)
+            redirect(action:"edit", id: params.id)
+            return
+        }
+
+        render(view:'edit', model:[assignedGroupInstance: result.assignedGroupInstance.attach(),
+                                                personGroup: result.personGroup.attach(),
+                                                personsInGroup: result.personsInGroup])
+    }
+
+    def create = {
+        def result = assignedGroupService.create(params)
+
+        if(!result.error) {
+            return [assignedGroupInstance: result.assignedGroupInstance,
+                            personGroup: result.personGroup,
+                            personsInGroup: result.personsInGroup]
+        }
+
+        if(result.error.code == "assignedGroup.task.not.found") {
+            flash.message = g.message(code: result.error.code, args: result.error.args)
+            redirect(controller: "taskDetailed", action: "search")
+            return
+        }
+
+        flash.message = g.message(code: result.error.code, args: result.error.args)
+        redirect(controller:"taskDetailed", action:"show", id: params.task?.id)
+    }
+
+    def save = {
+        def result = assignedGroupService.save(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.create.success", args: ["AssignedGroup", result.assignedGroupInstance.id])
+            redirect(controller:"taskDetailed", action:"show", id: result.assignedGroupInstance.task.id)
+            return
+        }
+
+        if(result.error.code == "personGroup.not.found") {
+            flash.message = g.message(code: result.error.code, args: result.error.args)
+            redirect(action:"create", params:["task.id": params.task?.id])
+            return
+        }
+
+        render(view:'create', model:[assignedGroupInstance: result.assignedGroupInstance,
+                                                personGroup: result.personGroup.attach(),
+                                                personsInGroup: result.personsInGroup])
+    }
+
+    def personsInGroup = {
+        def result = assignedGroupService.personsInGroup(params)
+
+        if(!result.error) {
+            render ( template:"personsInGroup",
+                            model: [personGroup: result.personGroup, personsInGroup: result.personsInGroup] )
+            return
+        }
+
+        render {
+            div(id:"personsInGroup", g.message(code: result.error.code, args: result.error.args) )
+        }
+
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/AssignedPersonDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/AssignedPersonDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/AssignedPersonDetailedController.groovy	(revision 753)
@@ -0,0 +1,130 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager'])
+class AssignedPersonDetailedController extends BaseController {
+
+    def assignedPersonService
+
+    def index = {
+        flash.message = g.message(code: "assignedPerson.task.not.found")
+        redirect(controller:"taskDetailed", action:"search")
+    }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def delete = {
+        def result = assignedPersonService.delete(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.delete.success", args: ["AssignedPerson", params.id])
+            redirect(controller:"taskDetailed", action:"show", id: params.task?.id)
+            return
+        }
+
+        flash.message = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.error.code == "default.not.found") {
+            redirect(controller:"taskDetailed", action:"show", id: params.task?.id)
+            return
+        }
+
+        redirect(action:show, id: params.id)
+    }
+
+    def edit = {
+        def result = assignedPersonService.edit(params)
+
+        if(!result.error) {
+            return [assignedPersonInstance: result.assignedPersonInstance,
+                            person: result.person,
+                            groupsForPerson: result.groupsForPerson]
+        }
+
+        flash.message = g.message(code: result.error.code, args: result.error.args)
+
+        redirect(controller:"taskDetailed", action:"show", id: params.task?.id)
+
+    }
+
+    def update = {
+        def result = assignedPersonService.update(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.update.success", args: ["AssignedPerson", params.id])
+            redirect(controller:"taskDetailed", action:"show", id: result.assignedPersonInstance.task.id)
+            return
+        }
+
+        if(result.error.code == "default.not.found") {
+            flash.message = g.message(code: result.error.code, args: result.error.args)
+            redirect(controller:"taskDetailed", action:"show", id: params.task?.id)
+            return
+        }
+
+        if(result.error.code == "person.not.found") {
+            flash.message = g.message(code: result.error.code, args: result.error.args)
+            redirect(action:"edit", id: params.id)
+            return
+        }
+
+        render(view:'edit', model:[assignedPersonInstance: result.assignedPersonInstance.attach(),
+                                                person: result.person.attach(),
+                                                groupsForPerson: result.groupsForPerson])
+    }
+
+    def create = {
+        def result = assignedPersonService.create(params)
+
+        if(!result.error) {
+            return [assignedPersonInstance: result.assignedPersonInstance,
+                            person: result.person,
+                            groupsForPerson: result.groupsForPerson]
+        }
+
+        if(result.error.code == "assignedPerson.task.not.found") {
+            flash.message = g.message(code: result.error.code, args: result.error.args)
+            redirect(controller: "taskDetailed", action: "search")
+            return
+        }
+
+        flash.message = g.message(code: result.error.code, args: result.error.args)
+        redirect(controller:"taskDetailed", action:"show", id: params.task?.id)
+    }
+
+    def save = {
+        def result = assignedPersonService.save(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.create.success", args: ["AssignedPerson", result.assignedPersonInstance.id])
+            redirect(controller:"taskDetailed", action:"show", id: result.assignedPersonInstance.task.id)
+            return
+        }
+
+        if(result.error.code == "person.not.found") {
+            flash.message = g.message(code: result.error.code, args: result.error.args)
+            redirect(action:"create", params:["task.id": params.task?.id])
+            return
+        }
+
+        render(view:'create', model:[assignedPersonInstance: result.assignedPersonInstance,
+                                                person: result.person.attach(),
+                                                groupsForPerson: result.groupsForPerson])
+    }
+
+    def groupsForPerson = {
+        def result = assignedPersonService.groupsForPerson(params)
+
+        if(!result.error) {
+            render ( template:"groupsForPerson",
+                            model: [person: result.person, groupsForPerson: result.groupsForPerson] )
+            return
+        }
+
+        render {
+            div(id:"groupsForPerson", g.message(code: result.error.code, args: result.error.args) )
+        }
+
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/AuthorityController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/AuthorityController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/AuthorityController.groovy	(revision 753)
@@ -0,0 +1,118 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class AuthorityController extends BaseAppAdminController {
+
+    // the delete, save and update actions only accept POST requests
+    static Map allowedMethods = [delete: 'POST', save: 'POST', update: 'POST']
+
+    def authenticateService
+
+    def index = {
+        redirect action: list, params: params
+    }
+
+    /**
+    * Display the list authority page.
+    */
+    def list = {
+        if (!params.max) {
+            params.max = 10
+        }
+        [authorityList: Authority.list(params)]
+    }
+
+    /**
+    * Display the show authority page.
+    */
+    def show = {
+        def authority = Authority.get(params.id)
+        if (!authority) {
+            flash.message = "Authority not found with id $params.id"
+            redirect action: list
+            return
+        }
+
+        [authority: authority]
+    }
+
+    /**
+    * Delete an authority.
+    */
+    def delete = {
+        def authority = Authority.get(params.id)
+        if (!authority) {
+            flash.message = "Authority not found with id $params.id"
+            redirect action: list
+            return
+        }
+
+        authenticateService.deleteRole(authority)
+
+        flash.message = "Authority $params.id deleted."
+        redirect action: list
+    }
+
+    /**
+    * Display the edit authority page.
+    */
+    def edit = {
+        def authority = Authority.get(params.id)
+        if (!authority) {
+            flash.message = "Authority not found with id $params.id"
+            redirect action: list
+            return
+        }
+
+        [authority: authority]
+    }
+
+    /**
+    * Authority update action.
+    */
+    def update = {
+
+        def authority = Authority.get(params.id)
+        if (!authority) {
+            flash.message = "Authority not found with id $params.id"
+            redirect action: edit, id: params.id
+            return
+        }
+
+        long version = params.version.toLong()
+        if (authority.version > version) {
+            authority.errors.rejectValue 'version', "default.optimistic.locking.failure"
+            render view: 'edit', model: [authority: authority]
+            return
+        }
+
+        if (authenticateService.updateRole(authority, params)) {
+            authenticateService.clearCachedRequestmaps()
+            redirect action: show, id: authority.id
+        }
+        else {
+            render view: 'edit', model: [authority: authority]
+        }
+    }
+
+    /**
+    * Display the create new authority page.
+    */
+    def create = {
+        [authority: new Authority()]
+    }
+
+    /**
+    * Save a new authority.
+    */
+    def save = {
+
+        def authority = new Authority()
+        authority.properties = params
+        if (authority.save(flush: true)) {
+            redirect action: show, id: authority.id
+        }
+        else {
+            render view: 'create', model: [authority: authority]
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/BaseAppAdminController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/BaseAppAdminController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/BaseAppAdminController.groovy	(revision 753)
@@ -0,0 +1,7 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin'])
+abstract class BaseAppAdminController {
+
+}
+
Index: branches/features/taskProcedureRework/grails-app/controllers/BaseController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/BaseController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/BaseController.groovy	(revision 753)
@@ -0,0 +1,7 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AppUser'])
+abstract class BaseController {
+
+}
+
Index: branches/features/taskProcedureRework/grails-app/controllers/ContactDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/ContactDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/ContactDetailedController.groovy	(revision 753)
@@ -0,0 +1,129 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                    'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager'])
+class ContactDetailedController extends BaseController {
+
+    def contactService
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                        'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager', 'ROLE_AppUser'])
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                        'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager', 'ROLE_AppUser'])
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ contactInstanceList: Contact.list( params ), contactInstanceTotal: Contact.count() ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager',
+                        'ROLE_InventoryManager', 'ROLE_AssetManager', 'ROLE_ProductionManager', 'ROLE_AppUser'])
+    def show = {
+        def contactInstance = Contact.get( params.id )
+
+        if(!contactInstance) {
+            flash.message = "Contact not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ contactInstance : contactInstance ] }
+    }
+
+    def delete = {
+        def result = contactService.delete(params)
+
+        if(!result.error) {
+            if(result.ownerInstance) {
+                def c = getControllerName(result.ownerInstance)
+                flash.message = g.message(code: "default.delete.success", args: ["Contact", ''])
+                redirect(controller:c, action:'edit', id: result.ownerInstance.id)
+                return
+            }
+            flash.message = g.message(code: "default.delete.success", args: ["Contact", params.id])
+            redirect(action:list)
+            return
+        }
+
+        flash.message = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.error.code == "default.not.found") {
+            redirect(action:list)
+            return
+        }
+
+        redirect(action:show, id: params.id)
+    }
+
+    def edit = {
+        def contactInstance = Contact.get( params.id )
+
+        if(!contactInstance) {
+            flash.message = "Contact not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ contactInstance : contactInstance ]
+        }
+    }
+
+    def update = {
+        def contactInstance = Contact.get( params.id )
+        if(contactInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(contactInstance.version > version) {
+
+                    contactInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[contactInstance:contactInstance])
+                    return
+                }
+            }
+            contactInstance.properties = params
+            if(!contactInstance.hasErrors() && contactInstance.save(flush: true)) {
+                flash.message = "Contact ${params.id} updated"
+                redirect(action:show,id:contactInstance.id)
+            }
+            else {
+                render(view:'edit',model:[contactInstance:contactInstance])
+            }
+        }
+        else {
+            flash.message = "Contact not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def result = contactService.create(params)
+
+        if(!result.error)
+            return [contactInstance: result.contactInstance]
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: list)
+    }
+
+    def save = {
+        def result = contactService.save(params)
+
+        if(!result.error) {
+            def c = getControllerName(result.ownerInstance)
+            flash.message = g.message(code: "default.create.success", args: ["Contact", ''])
+            redirect(controller:c, action:'edit', id: result.ownerInstance.id)
+            return
+        }
+
+        render(view:'create', model:[contactInstance: result.contactInstance])
+    }
+
+    private getControllerName(ownerInstance) {
+        if(ownerInstance.class.name == 'Person')
+            return "${ownerInstance.class.name[0].toLowerCase() + ownerInstance.class.name[1..-1]}"
+        else
+            return "${ownerInstance.class.name[0].toLowerCase() + ownerInstance.class.name[1..-1]}"+"Detailed"
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/CostCodeDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/CostCodeDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/CostCodeDetailedController.groovy	(revision 753)
@@ -0,0 +1,115 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
+class CostCodeDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ costCodeInstanceList: CostCode.list( params ), costCodeInstanceTotal: CostCode.count() ]
+    }
+
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def costCodeInstance = CostCode.get( params.id )
+
+        if(!costCodeInstance) {
+            flash.message = "CostCode not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ costCodeInstance : costCodeInstance ] }
+    }
+
+    def delete = {
+        def costCodeInstance = CostCode.get( params.id )
+        if(costCodeInstance) {
+            try {
+                costCodeInstance.delete(flush:true)
+                flash.message = "CostCode ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "CostCode ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "CostCode not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def costCodeInstance = CostCode.get( params.id )
+
+        if(!costCodeInstance) {
+            flash.message = "CostCode not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ costCodeInstance : costCodeInstance ]
+        }
+    }
+
+    def update = {
+        def costCodeInstance = CostCode.get( params.id )
+        if(costCodeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(costCodeInstance.version > version) {
+
+                    costCodeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[costCodeInstance:costCodeInstance])
+                    return
+                }
+            }
+            costCodeInstance.properties = params
+            // Trim name to avoid spaces.
+            costCodeInstance.name = costCodeInstance.name.trim()
+            if(!costCodeInstance.hasErrors() && costCodeInstance.save(flush: true)) {
+                flash.message = "CostCode ${params.id} updated"
+                redirect(action:show,id:costCodeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[costCodeInstance:costCodeInstance])
+            }
+        }
+        else {
+            flash.message = "CostCode not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def costCodeInstance = new CostCode()
+        costCodeInstance.properties = params
+        return ['costCodeInstance':costCodeInstance]
+    }
+
+    def save = {
+        def costCodeInstance = new CostCode(params)
+        // Trim name to avoid spaces.
+        costCodeInstance.name = costCodeInstance.name.trim()
+        if(!costCodeInstance.hasErrors() && costCodeInstance.save(flush: true)) {
+            flash.message = "CostCode ${costCodeInstance.id} created"
+            redirect(action:show,id:costCodeInstance.id)
+        }
+        else {
+            render(view:'create',model:[costCodeInstance:costCodeInstance])
+        }
+    } // save
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/controllers/DepartmentDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/DepartmentDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/DepartmentDetailedController.groovy	(revision 753)
@@ -0,0 +1,100 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
+class DepartmentDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ departmentInstanceList: Department.list( params ), departmentInstanceTotal: Department.count() ]
+    }
+
+    def show = {
+        def departmentInstance = Department.get( params.id )
+
+        if(!departmentInstance) {
+            flash.message = "Department not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ departmentInstance : departmentInstance ] }
+    }
+
+    def delete = {
+        def departmentInstance = Department.get( params.id )
+        if(departmentInstance) {
+            try {
+                departmentInstance.delete(flush:true)
+                flash.message = "Department ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "Department ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "Department not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def departmentInstance = Department.get( params.id )
+
+        if(!departmentInstance) {
+            flash.message = "Department not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ departmentInstance : departmentInstance ]
+        }
+    }
+
+    def update = {
+        def departmentInstance = Department.get( params.id )
+        if(departmentInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(departmentInstance.version > version) {
+                    
+                    departmentInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[departmentInstance:departmentInstance])
+                    return
+                }
+            }
+            departmentInstance.properties = params
+            if(!departmentInstance.hasErrors() && departmentInstance.save(flush: true)) {
+                flash.message = "Department ${params.id} updated"
+                redirect(action:show,id:departmentInstance.id)
+            }
+            else {
+                render(view:'edit',model:[departmentInstance:departmentInstance])
+            }
+        }
+        else {
+            flash.message = "Department not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def departmentInstance = new Department()
+        departmentInstance.properties = params
+        return ['departmentInstance':departmentInstance]
+    }
+
+    def save = {
+        def departmentInstance = new Department(params)
+        if(!departmentInstance.hasErrors() && departmentInstance.save(flush: true)) {
+            flash.message = "Department ${departmentInstance.id} created"
+            redirect(action:show,id:departmentInstance.id)
+        }
+        else {
+            render(view:'create',model:[departmentInstance:departmentInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/DepartmentExtendedAttributeDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/DepartmentExtendedAttributeDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/DepartmentExtendedAttributeDetailedController.groovy	(revision 753)
@@ -0,0 +1,100 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
+class DepartmentExtendedAttributeDetailedController extends BaseController {
+
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ departmentExtendedAttributeInstanceList: DepartmentExtendedAttribute.list( params ), departmentExtendedAttributeInstanceTotal: DepartmentExtendedAttribute.count() ]
+    }
+
+    def show = {
+        def departmentExtendedAttributeInstance = DepartmentExtendedAttribute.get( params.id )
+
+        if(!departmentExtendedAttributeInstance) {
+            flash.message = "DepartmentExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ departmentExtendedAttributeInstance : departmentExtendedAttributeInstance ] }
+    }
+
+    def delete = {
+        def departmentExtendedAttributeInstance = DepartmentExtendedAttribute.get( params.id )
+        if(departmentExtendedAttributeInstance) {
+            try {
+                departmentExtendedAttributeInstance.delete(flush:true)
+                flash.message = "DepartmentExtendedAttribute ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "DepartmentExtendedAttribute ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "DepartmentExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def departmentExtendedAttributeInstance = DepartmentExtendedAttribute.get( params.id )
+
+        if(!departmentExtendedAttributeInstance) {
+            flash.message = "DepartmentExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ departmentExtendedAttributeInstance : departmentExtendedAttributeInstance ]
+        }
+    }
+
+    def update = {
+        def departmentExtendedAttributeInstance = DepartmentExtendedAttribute.get( params.id )
+        if(departmentExtendedAttributeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(departmentExtendedAttributeInstance.version > version) {
+                    
+                    departmentExtendedAttributeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[departmentExtendedAttributeInstance:departmentExtendedAttributeInstance])
+                    return
+                }
+            }
+            departmentExtendedAttributeInstance.properties = params
+            if(!departmentExtendedAttributeInstance.hasErrors() && departmentExtendedAttributeInstance.save(flush: true)) {
+                flash.message = "DepartmentExtendedAttribute ${params.id} updated"
+                redirect(action:show,id:departmentExtendedAttributeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[departmentExtendedAttributeInstance:departmentExtendedAttributeInstance])
+            }
+        }
+        else {
+            flash.message = "DepartmentExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def departmentExtendedAttributeInstance = new DepartmentExtendedAttribute()
+        departmentExtendedAttributeInstance.properties = params
+        return ['departmentExtendedAttributeInstance':departmentExtendedAttributeInstance]
+    }
+
+    def save = {
+        def departmentExtendedAttributeInstance = new DepartmentExtendedAttribute(params)
+        if(!departmentExtendedAttributeInstance.hasErrors() && departmentExtendedAttributeInstance.save(flush: true)) {
+            flash.message = "DepartmentExtendedAttribute ${departmentExtendedAttributeInstance.id} created"
+            redirect(action:show,id:departmentExtendedAttributeInstance.id)
+        }
+        else {
+            render(view:'create',model:[departmentExtendedAttributeInstance:departmentExtendedAttributeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/EntryDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/EntryDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/EntryDetailedController.groovy	(revision 753)
@@ -0,0 +1,138 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+class EntryDetailedController extends BaseController {
+
+    def authService
+    def taskService
+
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        if(!params.max) params.max = 10
+        [ entryInstanceList: Entry.list( params ) ]
+    }
+
+    def show = {
+        def entryInstance = Entry.get( params.id )
+
+        if(!entryInstance) {
+            flash.message = "Entry not found with id ${params.id}"
+            redirect(controller: 'taskDetailed', action: 'search')
+        }
+        else { return [ entryInstance : entryInstance ] }
+    }
+
+    def delete = {
+        def entryInstance = Entry.get( params.id )
+        if(entryInstance) {
+            if(entryInstance.enteredBy.loginName == authService.currentUser.loginName) {
+                def taskID = entryInstance.task.id
+                entryInstance.delete(flush:true)
+                flash.message = "Entry ${params.id} deleted"
+                redirect(controller: 'taskDetailed', action: 'show', id: taskID)
+            }
+            else {
+                flash.message = "You may only delete your own entries."
+                redirect(action:show,id:entryInstance.id)
+            }
+
+        }
+        else {
+            flash.message = "Entry not found with id ${params.id}"
+            redirect(controller: "taskDetailed", action:"search")
+        }
+    }
+
+    def edit = {
+        def entryInstance = Entry.get( params.id )
+        if(!entryInstance) {
+                flash.message = "Entry not found with id ${params.id}"
+                redirect(controller: "taskDetailed", action:"search")
+        }
+        else {
+
+            if(entryInstance.enteredBy.loginName == authService.currentUser.loginName) {
+                return [ entryInstance : entryInstance ]
+            }
+            else {
+                flash.message = "You may only edit your own entries."
+                redirect(action:show,id:entryInstance.id)
+            }
+
+        }
+    }
+
+    def update = {
+        def entryInstance = Entry.get( params.id )
+        if(entryInstance) {
+            // The update method only accepts post requests, so this is just in case.
+            if(entryInstance.enteredBy.loginName == authService.currentUser.loginName) {
+                entryInstance.properties = params
+                if(!entryInstance.hasErrors() && entryInstance.save(flush: true)) {
+                    flash.message = "Entry ${params.id} updated"
+                    redirect(action:show,id:entryInstance.id)
+                }
+                else {
+                    render(view:'edit',model:[entryInstance:entryInstance])
+                }
+            }
+            else {
+                flash.message = "You may only edit your own entries."
+                redirect(action:show,id:entryInstance.id)
+            }
+        }
+        else {
+            flash.message = "Entry not found with id ${params.id}"
+            redirect(controller: "taskDetailed", action:"search")
+        }
+    }
+
+    def create = {
+        if(!params.taskInstance?.id || !params.entryType?.id) {
+            flash.message = g.message(code:"entry.create.no.params")
+            redirect(controller:"taskDetailed", action:"search")
+            return
+        }
+
+        def taskInstance = Task.read(params.taskInstance.id)
+
+        if(!taskInstance) {
+            flash.message = g.message(code:"task.notFound")
+            redirect(controller:"taskDetailed", action:"search")
+            return
+        }
+
+        // Check for Complete task.
+        if(taskInstance.taskStatus.id == 3) {
+            flash.errorMessage = g.message(code:"task.operationNotPermittedOnCompleteTask")
+            redirect(controller:"taskDetailed", action:"show", id: taskInstance.id)
+            return
+        }
+
+        def entryInstance = new Entry()
+        entryInstance.task = taskInstance
+        entryInstance.entryType = EntryType.read(params.entryType.id)
+        return ['entryInstance': entryInstance]
+    } // create
+
+    def save = {
+        def result = taskService.saveEntry(params)
+
+        if(!result.error) {
+            flash.message = "Entry created."
+            redirect(controller: "taskDetailed", action: "show", id: result.taskId)
+            return
+        }
+
+        if(result.error.code != "default.create.failure") {
+            params.errorMessage = g.message(code: result.error.code)
+        }
+
+        render(view:'create',model:[entryInstance: result.entryInstance])
+    } // save
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/controllers/EntryTypeController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/EntryTypeController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/EntryTypeController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class EntryTypeController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ entryTypeInstanceList: EntryType.list( params ), entryTypeInstanceTotal: EntryType.count() ]
+    }
+
+    def show = {
+        def entryTypeInstance = EntryType.get( params.id )
+
+        if(!entryTypeInstance) {
+            flash.message = "EntryType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ entryTypeInstance : entryTypeInstance ] }
+    }
+
+    def delete = {
+        def entryTypeInstance = EntryType.get( params.id )
+        if(entryTypeInstance) {
+            try {
+                entryTypeInstance.delete(flush:true)
+                flash.message = "EntryType ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "EntryType ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "EntryType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def entryTypeInstance = EntryType.get( params.id )
+
+        if(!entryTypeInstance) {
+            flash.message = "EntryType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ entryTypeInstance : entryTypeInstance ]
+        }
+    }
+
+    def update = {
+        def entryTypeInstance = EntryType.get( params.id )
+        if(entryTypeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(entryTypeInstance.version > version) {
+                    
+                    entryTypeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[entryTypeInstance:entryTypeInstance])
+                    return
+                }
+            }
+            entryTypeInstance.properties = params
+            if(!entryTypeInstance.hasErrors() && entryTypeInstance.save(flush: true)) {
+                flash.message = "EntryType ${params.id} updated"
+                redirect(action:show,id:entryTypeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[entryTypeInstance:entryTypeInstance])
+            }
+        }
+        else {
+            flash.message = "EntryType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def entryTypeInstance = new EntryType()
+        entryTypeInstance.properties = params
+        return ['entryTypeInstance':entryTypeInstance]
+    }
+
+    def save = {
+        def entryTypeInstance = new EntryType(params)
+        if(!entryTypeInstance.hasErrors() && entryTypeInstance.save(flush: true)) {
+            flash.message = "EntryType ${entryTypeInstance.id} created"
+            redirect(action:show,id:entryTypeInstance.id)
+        }
+        else {
+            render(view:'create',model:[entryTypeInstance:entryTypeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/ExtendedAttributeTypeDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/ExtendedAttributeTypeDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/ExtendedAttributeTypeDetailedController.groovy	(revision 753)
@@ -0,0 +1,110 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
+class ExtendedAttributeTypeDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ extendedAttributeTypeInstanceList: ExtendedAttributeType.list( params ), extendedAttributeTypeInstanceTotal: ExtendedAttributeType.count() ]
+    }
+
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def extendedAttributeTypeInstance = ExtendedAttributeType.get( params.id )
+
+        if(!extendedAttributeTypeInstance) {
+            flash.message = "ExtendedAttributeType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ extendedAttributeTypeInstance : extendedAttributeTypeInstance ] }
+    }
+
+    def delete = {
+        def extendedAttributeTypeInstance = ExtendedAttributeType.get( params.id )
+        if(extendedAttributeTypeInstance) {
+            try {
+                extendedAttributeTypeInstance.delete(flush:true)
+                flash.message = "ExtendedAttributeType ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "ExtendedAttributeType ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "ExtendedAttributeType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def extendedAttributeTypeInstance = ExtendedAttributeType.get( params.id )
+
+        if(!extendedAttributeTypeInstance) {
+            flash.message = "ExtendedAttributeType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ extendedAttributeTypeInstance : extendedAttributeTypeInstance ]
+        }
+    }
+
+    def update = {
+        def extendedAttributeTypeInstance = ExtendedAttributeType.get( params.id )
+        if(extendedAttributeTypeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(extendedAttributeTypeInstance.version > version) {
+                    
+                    extendedAttributeTypeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[extendedAttributeTypeInstance:extendedAttributeTypeInstance])
+                    return
+                }
+            }
+            extendedAttributeTypeInstance.properties = params
+            if(!extendedAttributeTypeInstance.hasErrors() && extendedAttributeTypeInstance.save(flush: true)) {
+                flash.message = "ExtendedAttributeType ${params.id} updated"
+                redirect(action:show,id:extendedAttributeTypeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[extendedAttributeTypeInstance:extendedAttributeTypeInstance])
+            }
+        }
+        else {
+            flash.message = "ExtendedAttributeType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def extendedAttributeTypeInstance = new ExtendedAttributeType()
+        extendedAttributeTypeInstance.properties = params
+        return ['extendedAttributeTypeInstance':extendedAttributeTypeInstance]
+    }
+
+    def save = {
+        def extendedAttributeTypeInstance = new ExtendedAttributeType(params)
+        if(!extendedAttributeTypeInstance.hasErrors() && extendedAttributeTypeInstance.save(flush: true)) {
+            flash.message = "ExtendedAttributeType ${extendedAttributeTypeInstance.id} created"
+            redirect(action:show,id:extendedAttributeTypeInstance.id)
+        }
+        else {
+            render(view:'create',model:[extendedAttributeTypeInstance:extendedAttributeTypeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/InventoryGroupDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/InventoryGroupDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/InventoryGroupDetailedController.groovy	(revision 753)
@@ -0,0 +1,113 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
+class InventoryGroupDetailedController extends BaseController {
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ inventoryGroupInstanceList: InventoryGroup.list( params ), inventoryGroupInstanceTotal: InventoryGroup.count() ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def inventoryGroupInstance = InventoryGroup.get( params.id )
+
+        if(!inventoryGroupInstance) {
+            flash.message = "InventoryGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ inventoryGroupInstance : inventoryGroupInstance ] }
+    }
+
+    def delete = {
+        def inventoryGroupInstance = InventoryGroup.get( params.id )
+        if(inventoryGroupInstance) {
+            try {
+                inventoryGroupInstance.delete(flush:true)
+                flash.message = "InventoryGroup ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "InventoryGroup ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "InventoryGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def inventoryGroupInstance = InventoryGroup.get( params.id )
+
+        if(!inventoryGroupInstance) {
+            flash.message = "InventoryGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ inventoryGroupInstance : inventoryGroupInstance ]
+        }
+    }
+
+    def update = {
+        def inventoryGroupInstance = InventoryGroup.get( params.id )
+        if(inventoryGroupInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(inventoryGroupInstance.version > version) {
+                    
+                    inventoryGroupInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[inventoryGroupInstance:inventoryGroupInstance])
+                    return
+                }
+            }
+            inventoryGroupInstance.properties = params
+            if(!inventoryGroupInstance.hasErrors() && inventoryGroupInstance.save(flush: true)) {
+                flash.message = "InventoryGroup ${params.id} updated"
+                redirect(action:show,id:inventoryGroupInstance.id)
+            }
+            else {
+                render(view:'edit',model:[inventoryGroupInstance:inventoryGroupInstance])
+            }
+        }
+        else {
+            flash.message = "InventoryGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def inventoryGroupInstance = new InventoryGroup()
+        inventoryGroupInstance.properties = params
+        return ['inventoryGroupInstance':inventoryGroupInstance]
+    }
+
+    def save = {
+        def inventoryGroupInstance = new InventoryGroup(params)
+        if(!inventoryGroupInstance.hasErrors() && inventoryGroupInstance.save(flush: true)) {
+            flash.message = "InventoryGroup ${inventoryGroupInstance.id} created"
+            redirect(action:show,id:inventoryGroupInstance.id)
+        }
+        else {
+            render(view:'create',model:[inventoryGroupInstance:inventoryGroupInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/InventoryItemDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/InventoryItemDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/InventoryItemDetailedController.groovy	(revision 753)
@@ -0,0 +1,703 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+import com.zeddware.grails.plugins.filterpane.FilterUtils
+import org.springframework.web.servlet.support.RequestContextUtils as RCU
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager'])
+class InventoryItemDetailedController extends BaseController {
+
+    def filterService
+    def exportService
+    def inventoryCsvService
+    def inventoryItemService
+    def inventoryItemSearchService
+    def inventoryMovementService
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST', useInventoryItem:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def index = { redirect(action:search, params:params) }
+
+    /**
+    * Set session.inventoryItemSearchParamsMax
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def setSearchParamsMax = {
+        def max = 1000
+        if(params.newMax?.isInteger()) {
+            def i = params.newMax.toInteger()
+            if(i > 0 && i <= max)
+                session.inventoryItemSearchParamsMax = params.newMax
+            if(i > max)
+                session.inventoryItemSearchParamsMax = max
+        }
+        forward(action: 'search', params: params)
+    }
+
+    /**
+    * Set session.inventoryItemReorderSearchParamsMax
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def setReorderSearchParamsMax = {
+        def max = 1000
+        if(params.newMax?.isInteger()) {
+            def i = params.newMax.toInteger()
+            if(i > 0 && i <= max)
+                session.inventoryItemReorderSearchParamsMax = params.newMax
+            if(i > max)
+                session.inventoryItemReorderSearchParamsMax = max
+        }
+        forward(action: 'reorder', params: params)
+    }
+
+    /**
+    * Display the import view.
+    */
+    def importInventoryItemPictures = {
+    }
+
+    /**
+    * Handle the import save.
+    */
+    def importInventoryItemPicturesSave = {
+        def result = inventoryItemService.importInventoryItemPictures(request)
+
+        if(!result.error) {
+            def logFileLink = g.link(controller: "appCore", action: "appLog") {"log"}
+            flash.message = g.message(code: "inventoryItemPictures.import.success", args: [logFileLink])
+            redirect(action:search)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: importInventoryItemPictures)
+    }
+
+    /**
+    * Display the import view.
+    */
+    def importInventory = {
+    }
+
+    /**
+    * Handle the import save.
+    */
+    def importInventorySave = {
+        def result = inventoryCsvService.importInventory(request)
+
+        if(!result.error) {
+            flash.message = g.message(code: "inventory.import.success")
+            redirect(action:search)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: importInventory)
+    }
+
+    /**
+    * Export a csv template.
+    * NOTE: IE has a 'validating' bug in dev mode that causes the export to take a long time!
+    * This does not appear to be a problem once deployed to Tomcat.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def exportInventoryTemplate = {
+        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
+        response.setHeader("Content-disposition", "attachment; filename=InventoryTemplate.csv")
+        def s = inventoryCsvService.buildInventoryTemplate()
+        render s
+    }
+
+    /**
+    * Export a csv test file.
+    */
+    def exportInventoryExample = {
+        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
+        response.setHeader("Content-disposition", "attachment; filename=InventoryExample.csv")
+        def s = inventoryCsvService.buildInventoryExample()
+        render s
+    }
+
+    /**
+    * Export the entire inventory as a csv file.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def exportInventory = {
+
+        def inventoryItemList = InventoryItem.list()
+
+        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
+        response.setHeader("Content-disposition", "attachment; filename=Inventory.csv")
+        def s = inventoryCsvService.buildInventory(inventoryItemList)
+        render s
+    }
+
+    /**
+    * Display the import view for purchases.
+    */
+    def importInventoryItemPurchases = {
+    }
+
+    /**
+    * Handle the inventory purchases import save.
+    */
+    def importInventoryItemPurchasesSave = {
+        def result = inventoryCsvService.importInventoryItemPurchases(request)
+
+        if(!result.error) {
+            flash.message = g.message(code: "inventory.import.success")
+            redirect(action:search)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: importInventoryItemPurchases)
+    }
+
+    /**
+    * Search for Inventory items.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def search = {
+
+        if(session.inventoryItemSearchParamsMax)
+            params.max = session.inventoryItemSearchParamsMax
+
+        // Protect filterPane.
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  1000)
+
+        def inventoryItemInstanceList = []
+        def inventoryItemInstanceTotal
+        def filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
+        def isFilterApplied = FilterUtils.isFilterApplied(params)
+
+        // Restore default sort if a new text search is requested
+        if(params.newTextSearch) {
+            params.sort = 'id'
+            params.order = 'desc'
+        }
+
+        // Restore search unless a new search is being requested.
+        if(!params.searchText && !params.quickSearch && !filterParams) {
+            if(session.inventoryItemSearchText) {
+                params.searchText = session.inventoryItemSearchText
+                params.searchName = session.inventoryItemSearchName
+                params.searchDescription = session.inventoryItemSearchDescription
+                params.searchComment = session.inventoryItemSearchComment
+                params.searchLocation = session.inventoryItemSearchLocation
+                params.searchGroup = session.inventoryItemSearchGroup
+                params.searchSpareFor = session.inventoryItemSearchSpareFor
+            }
+            else if(session.inventoryItemQuickSearch) {
+                params.quickSearch = session.inventoryItemQuickSearch
+                if(session.inventoryItemQuickSearchDaysBack)
+                    params.daysBack = session.inventoryItemQuickSearchDaysBack.toString()
+            }
+            else if(session.inventoryItemSearchFilterParams) {
+                session.inventoryItemSearchFilterParams.each() { params[it.key] = it.value }
+                params.filter = session.inventoryItemSearchFilter
+                isFilterApplied = FilterUtils.isFilterApplied(params)
+            }
+        }
+
+        // Remember sort if supplied, otherwise try to restore.
+        if(params.sort && params.order) {
+             session.inventoryItemSearchSort = params.sort
+             session.inventoryItemSearchOrder = params.order
+        }
+        else if(session.inventoryItemSearchSort && session.inventoryItemSearchOrder) {
+            params.sort = session.inventoryItemSearchSort
+            params.order = session.inventoryItemSearchOrder
+        }
+
+        if(isFilterApplied) {
+            // filterPane:
+            inventoryItemInstanceList = filterService.filter( params, InventoryItem )
+            inventoryItemInstanceTotal = filterService.count( params, InventoryItem )
+            filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
+            // Remember search.
+            session.inventoryItemSearchFilterParams = new LinkedHashMap(filterParams)
+            session.inventoryItemSearchFilter = new LinkedHashMap(params.filter)
+            // Clear any previous search.
+            session.removeAttribute("inventoryItemSearchText")
+            session.removeAttribute("inventoryItemSearchName")
+            session.removeAttribute("inventoryItemSearchDescription")
+            session.removeAttribute("inventoryItemSearchComment")
+            session.removeAttribute("inventoryItemSearchLocation")
+            session.removeAttribute("inventoryItemSearchGroup")
+            session.removeAttribute("inventoryItemSearchSpareFor")
+            session.removeAttribute("inventoryItemQuickSearch")
+            session.removeAttribute("inventoryItemQuickSearchDaysBack")
+        }
+        else if(params.searchText) {
+            // Text Search:
+            def result = inventoryItemSearchService.getTextSearch(params, RCU.getLocale(request))
+            inventoryItemInstanceList = result.inventoryItemList
+            inventoryItemInstanceTotal = result.inventoryItemList.totalCount
+            params.message = result.message
+            filterParams.searchText = result.searchText
+            // Place limit search selects in filterParams for pagination.
+            if(params.searchName)
+                filterParams.searchName = params.searchName
+            if(params.searchDescription)
+                filterParams.searchDescription = params.searchDescription
+            if(params.searchComment)
+                filterParams.searchComment = params.searchComment
+            if(params.searchLocation)
+                filterParams.searchLocation = params.searchLocation
+            if(params.searchGroup)
+                filterParams.searchGroup = params.searchGroup
+            if(params.searchSpareFor)
+                filterParams.searchSpareFor = params.searchSpareFor
+            // Remember search.
+            session.inventoryItemSearchText = params.searchText
+            session.inventoryItemSearchName = params.searchName
+            session.inventoryItemSearchDescription = params.searchDescription
+            session.inventoryItemSearchComment = params.searchComment
+            session.inventoryItemSearchLocation = params.searchLocation
+            session.inventoryItemSearchGroup = params.searchGroup
+            session.inventoryItemSearchSpareFor = params.searchSpareFor
+            // Clear any previous search.
+            session.removeAttribute("inventoryItemQuickSearch")
+            session.removeAttribute("inventoryItemQuickSearchDaysBack")
+            session.removeAttribute("inventoryItemSearchFilterParams")
+            session.removeAttribute("inventoryItemSearchFilter")
+        }
+        else {
+            // Quick Search Links:
+            if(!params.quickSearch) params.quickSearch = "all"
+            def result = inventoryItemSearchService.getQuickSearch(params, RCU.getLocale(request))
+            inventoryItemInstanceList = result.inventoryItemList
+            inventoryItemInstanceTotal = result.inventoryItemList.totalCount
+            params.message = result.message
+            filterParams.quickSearch = result.quickSearch
+            // Remember search.
+            session.inventoryItemQuickSearch = result.quickSearch
+            if(result.daysBack)
+                session.inventoryItemQuickSearchDaysBack = result.daysBack
+            // Clear any previous search.
+            session.removeAttribute("inventoryItemSearchText")
+            session.removeAttribute("inventoryItemSearchName")
+            session.removeAttribute("inventoryItemSearchDescription")
+            session.removeAttribute("inventoryItemSearchComment")
+            session.removeAttribute("inventoryItemSearchLocation")
+            session.removeAttribute("inventoryItemSearchGroup")
+            session.removeAttribute("inventoryItemSearchSpareFor")
+            session.removeAttribute("inventoryItemSearchFilterParams")
+            session.removeAttribute("inventoryItemSearchFilter")
+        }
+
+        // export plugin:
+        if(params?.format && params.format != "html") {
+
+            def dateFmt = { date ->
+                formatDate(format: "EEE, dd-MMM-yyyy", date: date)
+            }
+
+            String title
+            if(params.quickSearch)
+                title = params.message
+            else
+                title = "Filtered Inventory List."
+
+            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
+            response.setHeader("Content-disposition", "attachment; filename=Inventory.${params.extension}")
+            List fields = ["name",
+                                "description",
+                                "inventoryGroup",
+                                "unitsInStock",
+                                "reorderPoint",
+                                "unitOfMeasure",
+                                "inventoryLocation",
+                                "inventoryLocation.inventoryStore"]
+            Map labels = ["name": "Name",
+                                "description": "Description",
+                                "inventoryGroup": "Group",
+                                "unitsInStock":"In Stock",
+                                "reorderPoint":"Reorder Point",
+                                "unitOfMeasure": "UOM",
+                                "inventoryLocation": "Location",
+                                "inventoryLocation.inventoryStore": "Store"]
+
+            Map formatters = [:]
+            Map parameters = [title: title, separator: ","]
+
+            exportService.export(params.format,
+                                                response.outputStream,
+                                                inventoryItemInstanceList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) },
+                                                fields,
+                                                labels,
+                                                formatters,
+                                                parameters)
+        }
+
+        // Add some basic params to filterParams.
+        filterParams.max = params.max
+        filterParams.offset = params.offset?.toInteger() ?: 0
+        filterParams.sort = params.sort ?: "name"
+        filterParams.order = params.order ?: "asc"
+
+        // Get some associatedProperty values for filterpane.
+        def associatedPropertyValues = [:]
+        def associatedPropertyMax = 10000
+        associatedPropertyValues.inventoryLocationList = InventoryLocation.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        associatedPropertyValues.assetList = Asset.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        associatedPropertyValues.supplierList = Supplier.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+
+        return[ inventoryItemInstanceList: inventoryItemInstanceList,
+                        inventoryItemInstanceTotal: inventoryItemInstanceTotal,
+                        filterParams: filterParams,
+                        params: params,
+                        associatedPropertyValues: associatedPropertyValues ]
+    } // end search()
+
+    /**
+    * Simply assigns a passed in task id to a session variable and redirects to search.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def findInventoryItemForMovement = {
+        if(!params.task?.id) {
+            flash.message = "No task id supplied, please select a task then the inventory tab."
+            redirect(controller: "taskDetailed", action: "search")
+            return
+        }
+
+        session.inventoryMovementTaskId = params.task.id
+        flash.message = "Please find and then select the inventory item."
+        redirect(action: search)
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def result = inventoryItemService.show(params)
+
+        if(!result.error) {
+
+            def model = [ inventoryItemInstance: result.inventoryItemInstance,
+                                    inventoryMovementList: result.inventoryMovementList,
+                                    inventoryMovementListTotal: result.inventoryMovementListTotal,
+                                    inventoryMovementListMax: result.inventoryMovementListMax,
+                                    inventoryItemPurchases: result.inventoryItemPurchases,
+                                    inventoryItemPurchasesTotal: result.inventoryItemPurchasesTotal,
+                                    showTab: result.showTab]
+
+            if(session.inventoryMovementTaskId) {
+                model.inventoryMovementInstance = new InventoryMovement()
+                model.inventoryMovementInstance.task = Task.get(session.inventoryMovementTaskId)
+                model.inventoryMovementInstance.quantity = 1
+            }
+
+            // Success.
+            return model
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action:search)
+    }
+
+    def delete = {
+        def result = inventoryItemService.delete(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.delete.success", args: ["InventoryItem", params.id])
+            redirect(action:search)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.error.code == "default.not.found") {
+            redirect(action:search)
+            return
+        }
+
+        redirect(action:show, id: params.id)
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def result = inventoryItemService.edit(params)
+
+        if(!result.error) {
+            def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+
+            return [ inventoryItemInstance : result.inventoryItemInstance,
+                            suppliers: suppliers]
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action:search)
+    }
+
+    def update = {
+        def result = inventoryItemService.update(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.update.success", args: ["InventoryItem", params.id])
+            redirect(action:show, id: params.id)
+            return
+        }
+
+        if(result.error.code == "default.not.found") {
+            flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+            redirect(action:search)
+            return
+        }
+
+        def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+        render(view:'edit', model:[inventoryItemInstance: result.inventoryItemInstance,
+                                                suppliers: suppliers])
+    }
+
+    def create = {
+        def result = inventoryItemService.create(params)
+        def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+
+        if(!result.error)
+            return [inventoryItemInstance: result.inventoryItemInstance,
+                            suppliers: suppliers]
+
+        //flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: search)
+    }
+
+    def save = {
+        def result = inventoryItemService.save(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.create.success", args: ["InventoryItem", result.inventoryItemInstance.id])
+            redirect(action:show, id: result.inventoryItemInstance.id)
+            return
+        }
+
+        def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+
+        //flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        render(view:'create', model:[inventoryItemInstance: result.inventoryItemInstance,
+                                                    suppliers: suppliers])
+    }
+
+    /**
+    * Handles the use inventory item form submit in the show view.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def useInventoryItem = {
+
+        params.inventoryMovementType = InventoryMovementType.get(1) // Set type to "Used".
+        def result = inventoryMovementService.move(params)
+
+        if(!result.error) {
+            flash.message = "Inventory Movement for ${result.inventoryMovementInstance.inventoryItem.name.encodeAsHTML()} created."
+            session.inventoryMovementTaskId = null
+            redirect(controller: "taskDetailed",
+                            action: "show",
+                            id: result.taskId,
+                            params: [showTab: "showInventoryTab"])
+            // Success.
+            return
+        }
+
+        // Prepare data for the show view.
+        def p = [:]
+        p.id = result.inventoryMovementInstance.inventoryItem?.id
+        def r = inventoryItemService.show(p)
+
+        // Render show view if data was successfully prepared.
+        if(!r.error) {
+            def model = [ inventoryItemInstance: r.inventoryItemInstance,
+                                    inventoryMovementList: r.inventoryMovementList,
+                                    inventoryMovementListTotal: r.inventoryMovementListTotal,
+                                    inventoryMovementListMax: r.inventoryMovementListMax,
+                                    inventoryItemPurchases: r.inventoryItemPurchases,
+                                    inventoryItemPurchasesTotal: r.inventoryItemPurchasesTotal,
+                                    showTab: r.showTab]
+
+            model.inventoryMovementInstance = result.inventoryMovementInstance // This will pass in the errors.
+
+            render(view: 'show', model: model)
+            return
+        }
+
+        // Could not prepare data for show view so doing the next best thing.
+        flash.errorMessage = g.message(code: r.error.code, args: r.error.args)
+        redirect(action:search)
+
+    } // useInventoryItem
+
+    /**
+    * Clear the use inventory item form in the show view.
+    * Accomplished by clearing the session variable and ajax.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def clearUseInventoryItem = {
+            session.inventoryMovementTaskId = null
+            render ''
+    }
+
+    /**
+    * Search for Inventory items that require reorder.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager'])
+    def reorder = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_reorder)
+            params.action='reorder'
+
+        if(session.inventoryItemReorderSearchParamsMax)
+            params.max = session.inventoryItemReorderSearchParamsMax
+
+        def inventoryItemInstanceList = []
+        def inventoryItemInstanceTotal
+        def filterParams = params
+        def suppliers = Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+        def inventoryGroups = InventoryGroup.findAllByIsActive(true)
+
+        if(params.selectedGroups) {
+            if(params.selectedGroups instanceof String)
+                params.selectedGroups = [params.selectedGroups.toLong()]
+            else
+                params.selectedGroups = params.selectedGroups.collect { it.toLong() }
+        }
+        else
+                params.selectedGroups = []
+
+        // Restore search unless a new search is being requested.
+        if(!params.newSearch && !params.quickSearch) {
+            if(session.reorderSearchSelectedGroups) {
+                params.selectedGroups = session.reorderSearchSelectedGroups
+                params.selectedSupplier = session.reorderSearchSelectedSupplier
+                params.includeAlternateSuppliers = session.reorderSearchIncludeAlternateSuppliers
+                params.includeReorderListingDisabled = session.reorderSearchIncludeReorderListingDisabled
+                params.includeOnBackOrder = session.reorderSearchIncludeOnBackOrder
+            }
+            else if(session.inventoryItemReorderQuickSearch) {
+                params.quickSearch = session.inventoryItemReorderQuickSearch
+                if(session.inventoryItemReorderQuickSearchDaysBack)
+                    params.daysBack = session.inventoryItemReorderQuickSearchDaysBack.toString()
+            }
+        }
+
+        // Remember sort if supplied, otherwise try to restore.
+        if(params.sort && params.order) {
+             session.inventoryItemReorderSearchSort = params.sort
+             session.inventoryItemReorderSearchOrder = params.order
+        }
+        else if(session.inventoryItemReorderSearchSort && session.inventoryItemReorderSearchOrder) {
+            params.sort = session.inventoryItemReorderSearchSort
+            params.order = session.inventoryItemReorderSearchOrder
+        }
+
+        if(params.quickSearch) {
+            // Quick Search Links:
+            if(!params.quickSearch) params.quickSearch = "inventoryBelowReorder"
+            def result = inventoryItemSearchService.getQuickSearch(params, RCU.getLocale(request))
+            inventoryItemInstanceList = result.inventoryItemList
+            inventoryItemInstanceTotal = result.inventoryItemList.totalCount
+            params.message = result.message
+            filterParams.quickSearch = result.quickSearch
+            // Remember search.
+            session.inventoryItemReorderQuickSearch = result.quickSearch
+            if(result.daysBack)
+                session.inventoryItemReorderQuickSearchDaysBack = result.daysBack
+            // Clear any previous search.
+            session.removeAttribute("reorderSearchSelectedGroups")
+            session.removeAttribute("reorderSearchSelectedSupplier")
+            session.removeAttribute("reorderSearchIncludeAlternateSuppliers")
+            session.removeAttribute("reorderSearchIncludeReorderListingDisabled")
+            session.removeAttribute("reorderSearchIncludeOnBackOrder")
+        }
+        else {
+            // Reorder Search:
+            def result = inventoryItemSearchService.getReorderSearch(params, RCU.getLocale(request))
+            inventoryItemInstanceList = result.inventoryItemList
+            inventoryItemInstanceTotal = result.inventoryItemList.totalCount
+            params.message = result.message
+            // Place limit search selects in filterParams for pagination.
+            if(params.selectedGroups) {
+                filterParams.selectedGroups = params.selectedGroups
+                filterParams.selectedSupplier = params.selectedSupplier
+                filterParams.includeAlternateSuppliers = params.includeAlternateSuppliers
+                filterParams.includeReorderListingDisabled = params.includeReorderListingDisabled
+                filterParams.includeOnBackOrder = params.includeOnBackOrder
+            }
+            // Remember search.
+            session.reorderSearchSelectedGroups = params.selectedGroups
+            session.reorderSearchSelectedSupplier = params.selectedSupplier
+            session.reorderSearchIncludeAlternateSuppliers = params.includeAlternateSuppliers
+            session.reorderSearchIncludeReorderListingDisabled = params.includeReorderListingDisabled
+            session.reorderSearchIncludeOnBackOrder = params.includeOnBackOrder
+            // Clear any previous search.
+            session.removeAttribute("inventoryItemReorderQuickSearch")
+            session.removeAttribute("inventoryItemReorderQuickSearchDaysBack")
+        }
+
+        // export plugin:
+        if(params?.format && params.format != "html") {
+
+            def dateFmt = { date ->
+                formatDate(format: "EEE, dd-MMM-yyyy", date: date)
+            }
+
+            String title
+            if(params.quickSearch)
+                title = params.message
+            else
+                title = "Filtered Inventory List."
+
+            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
+            response.setHeader("Content-disposition", "attachment; filename=Inventory.${params.extension}")
+            List fields = ["name",
+                                "description",
+                                "inventoryGroup",
+                                "unitsInStock",
+                                "reorderPoint",
+                                "unitOfMeasure",
+                                "inventoryLocation",
+                                "inventoryLocation.inventoryStore"]
+            Map labels = ["name": "Name",
+                                "description": "Description",
+                                "inventoryGroup": "Group",
+                                "unitsInStock":"In Stock",
+                                "reorderPoint":"Reorder Point",
+                                "unitOfMeasure": "UOM",
+                                "inventoryLocation": "Location",
+                                "inventoryLocation.inventoryStore": "Store"]
+
+            Map formatters = [:]
+            Map parameters = [title: title, separator: ","]
+
+            exportService.export(params.format,
+                                                response.outputStream,
+                                                inventoryItemInstanceList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) },
+                                                fields,
+                                                labels,
+                                                formatters,
+                                                parameters)
+        }
+
+        // Add some basic params to filterParams.
+        filterParams.max = params.max
+        filterParams.offset = params.offset?.toInteger() ?: 0
+        filterParams.sort = params.sort ?: "name"
+        filterParams.order = params.order ?: "asc"
+
+        return[ inventoryItemInstanceList: inventoryItemInstanceList,
+                        inventoryItemInstanceTotal: inventoryItemInstanceTotal,
+                        filterParams: filterParams,
+                        params: params,
+                        inventoryGroups: inventoryGroups,
+                        suppliers: suppliers]
+    } // end reorder()
+
+} // end of class
Index: branches/features/taskProcedureRework/grails-app/controllers/InventoryItemPurchaseDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/InventoryItemPurchaseDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/InventoryItemPurchaseDetailedController.groovy	(revision 753)
@@ -0,0 +1,406 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+import com.zeddware.grails.plugins.filterpane.FilterUtils
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager'])
+class InventoryItemPurchaseDetailedController extends BaseController {
+
+    def authService
+    def filterService
+    def exportService
+    def dateUtilService
+    def inventoryPurchaseService
+
+    def index = {
+        redirect(action:'search', params:params)
+    }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def setSearchParamsMax = {
+        def max = 1000
+        if(params.newMax?.isInteger()) {
+            def i = params.newMax.toInteger()
+            if(i > 0 && i <= max)
+                session.inventoryItemPurchaseSearchParamsMax = params.newMax
+            if(i > max)
+                session.inventoryItemPurchaseSearchParamsMax = max
+        }
+        forward(action: 'search', params: params)
+    }
+
+    def search = {
+
+        if(session.inventoryItemPurchaseSearchParamsMax)
+            params.max = session.inventoryItemPurchaseSearchParamsMax
+
+        // Protect filterPane.
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  1000 )
+        params.offset = params.offset?.toInteger() ?: 0
+
+        def inventoryItemPurchaseList = []
+        def inventoryItemPurchaseTotal
+        def filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
+        def isFilterApplied = FilterUtils.isFilterApplied(params)
+
+        // Restore search unless a new search is being requested.
+        if(!params.quickSearch && !filterParams) {
+            if(session.inventoryItemPurchaseQuickSearch)
+                params.quickSearch = session.inventoryItemPurchaseQuickSearch
+            else if(session.inventoryItemPurchaseSearchFilterParams) {
+                session.inventoryItemPurchaseSearchFilterParams.each() { params[it.key] = it.value }
+                params.filter = session.inventoryItemPurchaseSearchFilter
+                isFilterApplied = FilterUtils.isFilterApplied(params)
+            }
+        }
+
+        // Remember sort if supplied, otherwise try to restore.
+        if(params.sort && params.order) {
+            // Reset to defaultSort if requested.
+            if(params.sort == 'defaultSort') {
+                params.sort = null
+                params.order = null
+                session.removeAttribute("inventoryItemPurchaseSearchSort")
+                session.removeAttribute("inventoryItemPurchaseSearchOrder")
+            }
+            else {
+                session.inventoryItemPurchaseSearchSort = params.sort
+                session.inventoryItemPurchaseSearchOrder = params.order
+            }
+        }
+        else if(session.inventoryItemPurchaseSearchSort && session.inventoryItemPurchaseSearchOrder) {
+            params.sort = session.inventoryItemPurchaseSearchSort
+            params.order = session.inventoryItemPurchaseSearchOrder
+        }
+        else {
+            params.sort = "id"
+            params.order = "asc"
+        }
+
+        if(isFilterApplied) {
+            // filterPane:
+            //if(params.sort == "attentionFlag") // See ticket #64 in Trac.
+                //params.sort = "id"
+
+            // Call filterService.
+            inventoryItemPurchaseList = filterService.filter( params, InventoryItemPurchase )
+            inventoryItemPurchaseTotal = filterService.count( params, InventoryItemPurchase )
+            filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
+            // Remember search.
+            session.inventoryItemPurchaseSearchFilterParams = new LinkedHashMap(filterParams)
+            session.inventoryItemPurchaseSearchFilter = new LinkedHashMap(params.filter)
+            session.removeAttribute("inventoryItemPurchaseQuickSearch")
+        }
+        else {
+            // Quick Search:
+
+            if(params.quickSearch == "searchAllOrders") {
+                def orderType = InventoryItemPurchaseType.read(1)
+                inventoryItemPurchaseList = InventoryItemPurchase.findAllByInventoryItemPurchaseType(orderType,
+                                                                                                                                                                [max:params.max,
+                                                                                                                                                                offset:params.offset,
+                                                                                                                                                                sort:params.sort,
+                                                                                                                                                                order:params.order])
+                inventoryItemPurchaseTotal = InventoryItemPurchase.countByInventoryItemPurchaseType(orderType)
+                if(inventoryItemPurchaseTotal > 0) { params.message = "All Orders." }
+                else { params.message = "No orders found." }
+            }
+            else if(params.quickSearch == "searchAllReceived") {
+                def receivedBackOrderType = InventoryItemPurchaseType.read(2)
+                def receivedCompleteType = InventoryItemPurchaseType.read(3)
+                inventoryItemPurchaseList = InventoryItemPurchase.findAllByInventoryItemPurchaseTypeOrInventoryItemPurchaseType(receivedBackOrderType,
+                                                                                                                                                                                                                receivedCompleteType,
+                                                                                                                                                                                                                [max:params.max,
+                                                                                                                                                                                                                offset:params.offset,
+                                                                                                                                                                                                                sort:params.sort,
+                                                                                                                                                                                                                order:params.order])
+                inventoryItemPurchaseTotal = InventoryItemPurchase.countByInventoryItemPurchaseTypeOrInventoryItemPurchaseType(receivedBackOrderType,
+                                                                                                                                                                                                                receivedCompleteType)
+                if(inventoryItemPurchaseTotal > 0) { params.message = "All Received." }
+                else { params.message = "No orders found." }
+            }
+            else {
+                //Default:
+                inventoryItemPurchaseList = InventoryItemPurchase.list(max:params.max,
+                                                                                                            offset:params.offset,
+                                                                                                            sort:params.sort,
+                                                                                                            order:params.order)
+                inventoryItemPurchaseTotal = InventoryItemPurchase.count()
+                if(inventoryItemPurchaseTotal > 0) { params.message = "All Purchases." }
+                else { params.message = "No orders found." }
+            }
+
+            filterParams.quickSearch = params.quickSearch
+            // Remember search.
+            session.removeAttribute("inventoryItemPurchaseSearchFilterParams")
+            session.removeAttribute("inventoryItemPurchaseSearchFilter")
+            session.inventoryItemPurchaseQuickSearch = params.quickSearch
+        }
+
+        // export plugin:
+        if(params?.format && params.format != "html") {
+
+            def dateFmt = { date ->
+                formatDate(format: "EEE, dd-MMM-yyyy", date: date)
+            }
+
+            String title
+            if(params.quickSearch)
+                title = "${params.quickSearch} inventory purchases."
+            else
+                title = "Filtered inventory purchases."
+
+            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
+            response.setHeader("Content-disposition", "attachment; filename=Purchases.${params.extension}")
+            List fields = ["purchaseOrderNumber", "date", "costCode", "quantity", "orderValueAmount", "invoiceNumber",
+                                    "inventoryItemPurchaseType"]
+            Map labels = ["purchaseOrderNumber": "Order Number", "date": "Date", "costCode": "Cost Code",
+                                    "quantity": "Quantity", "orderValueAmount": "Order \$", "invoiceNumber": "Invoice Number",
+                                    "inventoryItemPurchaseType": "Type"]
+            Map formatters = [ date: dateFmt]
+            Map parameters = [title: title, separator: ","]
+
+            exportService.export(params.format, response.outputStream, inventoryItemPurchaseList, fields, labels, formatters, parameters)
+        }
+
+        // Add some basic params to filterParams.
+        filterParams.max = params.max
+        filterParams.offset = params.offset?.toInteger() ?: 0
+        filterParams.sort = params.sort ?: "purchaseOrderNumber"
+        filterParams.order = params.order ?: "desc"
+
+        // Get some associatedProperty values for filterpane.
+        def associatedPropertyValues = [:]
+        def startOfYearRange = dateUtilService.getYearFromDate(dateUtilService.plusYear(new Date(), -10))
+        def endOfYearRange = dateUtilService.getYearFromDate(dateUtilService.plusYear(new Date(), 10))
+        associatedPropertyValues.yearRange = startOfYearRange..endOfYearRange
+
+        return[ inventoryItemPurchaseList: inventoryItemPurchaseList,
+                        inventoryItemPurchaseTotal: inventoryItemPurchaseTotal,
+                        filterParams: filterParams,
+                        associatedPropertyValues: associatedPropertyValues ]
+
+    } // end search()
+
+    def show = {
+        def inventoryItemPurchaseInstance = InventoryItemPurchase.read( params.id )
+        params.returnTo = params.returnTo ?: 'inventoryItem'
+
+        if(!inventoryItemPurchaseInstance) {
+            flash.message = "InventoryItemPurchase not found with id ${params.id}"
+            redirect(controller: 'inventoryItemDetailed', action:'search')
+        }
+        else { return [ inventoryItemPurchaseInstance : inventoryItemPurchaseInstance ] }
+    }
+
+    def delete = {
+        def result = inventoryPurchaseService.delete(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.delete.success", args: ["InventoryItemPurchase", params.id])
+            if(params.returnTo == 'inventoryItem') {
+                redirect(controller: 'inventoryItemDetailed',
+                                action: 'show',
+                                id: result.inventoryItemId,
+                                params: [showTab: "showPurchasingTab"])
+            }
+            else {
+                redirect(action: 'search')
+            }
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.error.code == "default.not.found") {
+            redirect(controller: 'inventoryItemDetailed', action: 'search')
+            return
+        }
+
+        redirect(action:show, id: params.id)
+    }
+
+    def edit = {
+        def result = inventoryPurchaseService.edit(params)
+        params.returnTo = params.returnTo ?: 'inventoryItem'
+
+        def costCodes = []
+
+        if(!result.error) {
+            if(inventoryPurchaseService.isPersonInPurchasingGroup(result.inventoryItemPurchaseInstance.costCode.purchasingGroup))
+                costCodes = inventoryPurchaseService.getCostCodesByPerson()
+
+            return [ inventoryItemPurchaseInstance : result.inventoryItemPurchaseInstance,
+                            'costCodes': costCodes ]
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(controller: 'inventoryItemDetailed', action:'search', params:params)
+    }
+
+    def update = {
+        def result = inventoryPurchaseService.update(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.update.success", args: ["Inventory Purchase", params.id])
+            redirect(action:show, id: params.id)
+            return
+        }
+
+        if(result.error.code == "default.not.found") {
+            flash.message = g.message(code: result.error.code, args: result.error.args)
+            redirect(controller: 'inventoryItemDetailed', action:'search', params:params)
+            return
+        }
+
+        result.inventoryItemPurchaseInstance.attach()
+        result.inventoryItemPurchaseInstance.costCode.attach()
+        result.inventoryItemPurchaseInstance.costCode.purchasingGroup.attach()
+
+        def costCodes = []
+        if(inventoryPurchaseService.isPersonInPurchasingGroup(result.inventoryItemPurchaseInstance.costCode.purchasingGroup))
+            costCodes = inventoryPurchaseService.getCostCodesByPerson()
+
+        render(view:'edit', model:[inventoryItemPurchaseInstance: result.inventoryItemPurchaseInstance,
+                                                'costCodes': costCodes])
+    }
+
+    def create = {
+        def inventoryItemPurchaseInstance = new InventoryItemPurchase()
+        inventoryItemPurchaseInstance.properties = params
+        params.returnTo = params.returnTo ?: 'inventoryItem'
+
+        if(!inventoryItemPurchaseInstance.inventoryItem) {
+            flash.message = "Please select an inventory item then the 'purchasing' tab."
+            redirect(controller: 'inventoryItemDetailed', action: 'search')
+            return
+        }
+
+        def costCodes = inventoryPurchaseService.getCostCodesByPerson()
+
+        return ['inventoryItemPurchaseInstance': inventoryItemPurchaseInstance,
+                        'costCodes': costCodes]
+    }
+
+    def save = {
+        def result = inventoryPurchaseService.save(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.create.success", args: ["Inventory Purchase", ''])
+            if(params.returnTo == 'inventoryItem') {
+                redirect(controller: 'inventoryItemDetailed',
+                                action: 'show',
+                                id: result.inventoryItemId,
+                                params: [showTab: "showPurchasingTab"])
+            }
+            else {
+                redirect(action: 'search')
+            }
+            return
+        }
+
+        def costCodes = inventoryPurchaseService.getCostCodesByPerson()
+
+        params.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        render(view:'create', model:['inventoryItemPurchaseInstance': result.inventoryItemPurchaseInstance,
+                                                    'costCodes': costCodes])
+    }
+
+    def receive = {
+        def inventoryItemPurchaseInstance = InventoryItemPurchase.read( params.id )
+
+        if(!inventoryItemPurchaseInstance) {
+            flash.message = "InventoryItemPurchase not found with id ${params.id}"
+            redirect(controller: 'inventoryItemDetailed', action:'search')
+            return
+        }
+
+        inventoryItemPurchaseInstance.properties = params
+        params.returnTo = params.returnTo ?: 'inventoryItem'
+        def calcQuantities = inventoryPurchaseService.calcQuantities(inventoryItemPurchaseInstance)
+        inventoryItemPurchaseInstance.quantity = calcQuantities.thisOrderRemaining
+        inventoryItemPurchaseInstance.orderValueAmount = calcQuantities.thisOrderRemainingAmount
+        return ['inventoryItemPurchaseInstance':inventoryItemPurchaseInstance,
+                        'orderId': inventoryItemPurchaseInstance.id]
+    }
+
+    def receiveSave = {
+        def result = inventoryPurchaseService.receiveSave(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.create.success", args: ["Inventory Purchase", ''])
+            if(params.returnTo == 'inventoryItem') {
+                redirect(controller: 'inventoryItemDetailed',
+                                action: 'show',
+                                id: result.inventoryItemId,
+                                params: [showTab: "showPurchasingTab"])
+            }
+            else {
+                redirect(action: 'search')
+            }
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.error.code == "default.not.found") {
+            redirect(controller: 'inventoryItemDetailed', action: 'search')
+            return
+        }
+
+        // Prevent lazy initialization error.
+        result.inventoryItemPurchaseInstance.costCode.attach()
+
+        render(view:'receive',
+                        model:['inventoryItemPurchaseInstance': result.inventoryItemPurchaseInstance,
+                                    'orderId': result.orderId])
+    }
+
+    def approveInvoicePayment = {
+        // Read the values from Order Received.
+        def inventoryItemPurchaseInstance = InventoryItemPurchase.read( params.id )
+
+        if(!inventoryItemPurchaseInstance) {
+            flash.message = "InventoryItemPurchase not found with id ${params.id}"
+            redirect(controller: 'inventoryItemDetailed', action:'search')
+            return
+        }
+
+        inventoryItemPurchaseInstance.properties = params
+        params.returnTo = params.returnTo ?: 'inventoryItem'
+        return ['inventoryItemPurchaseInstance':inventoryItemPurchaseInstance,
+                        'receivedId': inventoryItemPurchaseInstance.id]
+    }
+
+    def approveInvoicePaymentSave = {
+        def result = inventoryPurchaseService.approveInvoicePaymentSave(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.create.success", args: ["Inventory Purchase", ''])
+            if(params.returnTo == 'inventoryItem') {
+                redirect(controller: 'inventoryItemDetailed',
+                                action: 'show',
+                                id: result.inventoryItemId,
+                                params: [showTab: "showPurchasingTab"])
+            }
+            else {
+                redirect(action: 'search')
+            }
+            return
+        }
+
+        if(result.error.code == "default.not.found") {
+            flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+            redirect(controller: 'inventoryItemDetailed', action: 'search')
+            return
+        }
+
+        // Prevent lazy initialization error.
+        result.inventoryItemPurchaseInstance.costCode.attach()
+
+        render(view:'approveInvoicePayment',
+                    model:['inventoryItemPurchaseInstance': result.inventoryItemPurchaseInstance,
+                                    'receivedId': result.receivedId])
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/InventoryLocationDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/InventoryLocationDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/InventoryLocationDetailedController.groovy	(revision 753)
@@ -0,0 +1,113 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager'])
+class InventoryLocationDetailedController extends BaseController {
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def index = { redirect(action:list,params:params) }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ inventoryLocationInstanceList: InventoryLocation.list( params ), inventoryLocationInstanceTotal: InventoryLocation.count() ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def inventoryLocationInstance = InventoryLocation.get( params.id )
+
+        if(!inventoryLocationInstance) {
+            flash.message = "InventoryLocation not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ inventoryLocationInstance : inventoryLocationInstance ] }
+    }
+
+    def delete = {
+        def inventoryLocationInstance = InventoryLocation.get( params.id )
+        if(inventoryLocationInstance) {
+            try {
+                inventoryLocationInstance.delete(flush:true)
+                flash.message = "InventoryLocation ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "InventoryLocation ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "InventoryLocation not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def inventoryLocationInstance = InventoryLocation.get( params.id )
+
+        if(!inventoryLocationInstance) {
+            flash.message = "InventoryLocation not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ inventoryLocationInstance : inventoryLocationInstance ]
+        }
+    }
+
+    def update = {
+        def inventoryLocationInstance = InventoryLocation.get( params.id )
+        if(inventoryLocationInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(inventoryLocationInstance.version > version) {
+                    
+                    inventoryLocationInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[inventoryLocationInstance:inventoryLocationInstance])
+                    return
+                }
+            }
+            inventoryLocationInstance.properties = params
+            if(!inventoryLocationInstance.hasErrors() && inventoryLocationInstance.save(flush: true)) {
+                flash.message = "InventoryLocation ${params.id} updated"
+                redirect(action:show,id:inventoryLocationInstance.id)
+            }
+            else {
+                render(view:'edit',model:[inventoryLocationInstance:inventoryLocationInstance])
+            }
+        }
+        else {
+            flash.message = "InventoryLocation not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def inventoryLocationInstance = new InventoryLocation()
+        inventoryLocationInstance.properties = params
+        return ['inventoryLocationInstance':inventoryLocationInstance]
+    }
+
+    def save = {
+        def inventoryLocationInstance = new InventoryLocation(params)
+        if(!inventoryLocationInstance.hasErrors() && inventoryLocationInstance.save(flush: true)) {
+            flash.message = "InventoryLocation ${inventoryLocationInstance.id} created"
+            redirect(action:show,id:inventoryLocationInstance.id)
+        }
+        else {
+            render(view:'create',model:[inventoryLocationInstance:inventoryLocationInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/InventoryMovementDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/InventoryMovementDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/InventoryMovementDetailedController.groovy	(revision 753)
@@ -0,0 +1,116 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager'])
+class InventoryMovementDetailedController extends BaseController {
+
+    def inventoryMovementService
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST']
+
+    def index = { redirect(action:list,params:params) }
+
+    def list = {
+        flash.message = flash.message
+        redirect(controller:"taskDetailed", action:"search")
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def show = {
+        def inventoryMovementInstance = InventoryMovement.get( params.id )
+
+        if(!inventoryMovementInstance) {
+            flash.message = "InventoryMovement not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ inventoryMovementInstance : inventoryMovementInstance ] }
+    }
+
+    /**
+    * List the inventory movements for an InventoryItem.
+    * @param params.inventoryItem.id The id of an existing inventory item.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def listInventoryMovements = {
+        def inventoryItemInstance
+        if(params.id)
+            inventoryItemInstance = InventoryItem.get(params.id)
+        else if(params.inventoryItem?.id)
+            inventoryItemInstance = InventoryItem.get(params.inventoryItem.id)
+
+        if(!inventoryItemInstance) {
+            flash.message = "Inventory item not found with id ${params.id}"
+            redirect(controller:'inventoryItemDetailed', action: 'search')
+            return
+        }
+
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        def inventoryMovementList = InventoryMovement.findAllByInventoryItem(inventoryItemInstance, params)
+        def inventoryMovementListTotal = InventoryMovement.countByInventoryItem(inventoryItemInstance)
+
+        [ inventoryMovementList: inventoryMovementList,
+            inventoryMovementListTotal:  inventoryMovementListTotal,
+            inventoryItemInstance: inventoryItemInstance]
+    }
+
+    def delete = {
+        def result = inventoryMovementService.reverseMove(params)
+
+        if(!result.error) {
+            flash.message = "InventoryMovement ${params.id} deleted"
+            if(result.taskId) {
+                redirect(controller:"taskDetailed", action:"show", id:result.taskId)
+                return
+            }
+            redirect(controller:"inventoryItemDetailed", action:"show", id:result.inventoryItemInstance?.id)
+        }
+        else {
+            if(result.inventoryMovementInstance) {
+                render(view:'show',model:[inventoryMovementInstance:result.inventoryMovementInstance.attach()])
+            }
+            else {
+                flash.message = "Could not delete inventory movement."
+                redirect(controller:"taskDetailed", action:"search")
+            }
+        }
+    }
+
+    def create = {
+        def inventoryMovementInstance = new InventoryMovement()
+        inventoryMovementInstance.properties = params
+        def inventoryMovementTypeList = InventoryMovementType.withCriteria { gt("id", 1L) } // Don't include "Used".
+
+        return ['inventoryMovementInstance': inventoryMovementInstance,
+                        inventoryMovementTypeList: inventoryMovementTypeList]
+    }
+
+    /**
+    * Handles all inventory movements except those of type "Used".
+     * The "Used" type is handled directly by InventoryItemDetailedController and useInventoryItem.
+    */
+    def save = {
+        def result = inventoryMovementService.move(params)
+
+        if(!result.error) {
+            flash.message = "Inventory Movement for ${result.inventoryMovementInstance.inventoryItem.name} created."
+            if(result.taskId) {
+                redirect(controller:"taskDetailed", action:"show", id: result.taskId)
+                return
+            }
+            redirect(controller:"inventoryItemDetailed", action:"show", id: result.inventoryMovementInstance.inventoryItem.id)
+        }
+        else {
+            if(result.inventoryMovementInstance) {
+                def inventoryMovementTypeList = InventoryMovementType.withCriteria { gt("id", 1L) } // Don't include "Used".
+                render(view:'create', model:[inventoryMovementInstance: result.inventoryMovementInstance,
+                                                            inventoryMovementTypeList: inventoryMovementTypeList])
+            }
+            else {
+                flash.message = "Could not create inventory movement."
+                redirect(controller:"taskDetailed", action:"search", id:result.taskId)
+            }
+
+        }
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/InventoryMovementTypeController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/InventoryMovementTypeController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/InventoryMovementTypeController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class InventoryMovementTypeController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ inventoryMovementTypeInstanceList: InventoryMovementType.list( params ), inventoryMovementTypeInstanceTotal: InventoryMovementType.count() ]
+    }
+
+    def show = {
+        def inventoryMovementTypeInstance = InventoryMovementType.get( params.id )
+
+        if(!inventoryMovementTypeInstance) {
+            flash.message = "InventoryMovementType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ inventoryMovementTypeInstance : inventoryMovementTypeInstance ] }
+    }
+
+    def delete = {
+        def inventoryMovementTypeInstance = InventoryMovementType.get( params.id )
+        if(inventoryMovementTypeInstance) {
+            try {
+                inventoryMovementTypeInstance.delete(flush:true)
+                flash.message = "InventoryMovementType ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "InventoryMovementType ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "InventoryMovementType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def inventoryMovementTypeInstance = InventoryMovementType.get( params.id )
+
+        if(!inventoryMovementTypeInstance) {
+            flash.message = "InventoryMovementType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ inventoryMovementTypeInstance : inventoryMovementTypeInstance ]
+        }
+    }
+
+    def update = {
+        def inventoryMovementTypeInstance = InventoryMovementType.get( params.id )
+        if(inventoryMovementTypeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(inventoryMovementTypeInstance.version > version) {
+                    
+                    inventoryMovementTypeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[inventoryMovementTypeInstance:inventoryMovementTypeInstance])
+                    return
+                }
+            }
+            inventoryMovementTypeInstance.properties = params
+            if(!inventoryMovementTypeInstance.hasErrors() && inventoryMovementTypeInstance.save(flush: true)) {
+                flash.message = "InventoryMovementType ${params.id} updated"
+                redirect(action:show,id:inventoryMovementTypeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[inventoryMovementTypeInstance:inventoryMovementTypeInstance])
+            }
+        }
+        else {
+            flash.message = "InventoryMovementType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def inventoryMovementTypeInstance = new InventoryMovementType()
+        inventoryMovementTypeInstance.properties = params
+        return ['inventoryMovementTypeInstance':inventoryMovementTypeInstance]
+    }
+
+    def save = {
+        def inventoryMovementTypeInstance = new InventoryMovementType(params)
+        if(!inventoryMovementTypeInstance.hasErrors() && inventoryMovementTypeInstance.save(flush: true)) {
+            flash.message = "InventoryMovementType ${inventoryMovementTypeInstance.id} created"
+            redirect(action:show,id:inventoryMovementTypeInstance.id)
+        }
+        else {
+            render(view:'create',model:[inventoryMovementTypeInstance:inventoryMovementTypeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/InventoryStoreDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/InventoryStoreDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/InventoryStoreDetailedController.groovy	(revision 753)
@@ -0,0 +1,112 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager'])
+class InventoryStoreDetailedController extends BaseController {
+    
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ inventoryStoreInstanceList: InventoryStore.list( params ), inventoryStoreInstanceTotal: InventoryStore.count() ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def inventoryStoreInstance = InventoryStore.get( params.id )
+
+        if(!inventoryStoreInstance) {
+            flash.message = "InventoryStore not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ inventoryStoreInstance : inventoryStoreInstance ] }
+    }
+
+    def delete = {
+        def inventoryStoreInstance = InventoryStore.get( params.id )
+        if(inventoryStoreInstance) {
+            try {
+                inventoryStoreInstance.delete(flush:true)
+                flash.message = "InventoryStore ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "InventoryStore ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "InventoryStore not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def inventoryStoreInstance = InventoryStore.get( params.id )
+
+        if(!inventoryStoreInstance) {
+            flash.message = "InventoryStore not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ inventoryStoreInstance : inventoryStoreInstance ]
+        }
+    }
+
+    def update = {
+        def inventoryStoreInstance = InventoryStore.get( params.id )
+        if(inventoryStoreInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(inventoryStoreInstance.version > version) {
+                    
+                    inventoryStoreInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[inventoryStoreInstance:inventoryStoreInstance])
+                    return
+                }
+            }
+            inventoryStoreInstance.properties = params
+            if(!inventoryStoreInstance.hasErrors() && inventoryStoreInstance.save(flush: true)) {
+                flash.message = "InventoryStore ${params.id} updated"
+                redirect(action:show,id:inventoryStoreInstance.id)
+            }
+            else {
+                render(view:'edit',model:[inventoryStoreInstance:inventoryStoreInstance])
+            }
+        }
+        else {
+            flash.message = "InventoryStore not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def inventoryStoreInstance = new InventoryStore()
+        inventoryStoreInstance.properties = params
+        return ['inventoryStoreInstance':inventoryStoreInstance]
+    }
+
+    def save = {
+        def inventoryStoreInstance = new InventoryStore(params)
+        if(!inventoryStoreInstance.hasErrors() && inventoryStoreInstance.save(flush: true)) {
+            flash.message = "InventoryStore ${inventoryStoreInstance.id} created"
+            redirect(action:show,id:inventoryStoreInstance.id)
+        }
+        else {
+            render(view:'create',model:[inventoryStoreInstance:inventoryStoreInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/InventoryTypeController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/InventoryTypeController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/InventoryTypeController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class InventoryTypeController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ inventoryTypeInstanceList: InventoryType.list( params ), inventoryTypeInstanceTotal: InventoryType.count() ]
+    }
+
+    def show = {
+        def inventoryTypeInstance = InventoryType.get( params.id )
+
+        if(!inventoryTypeInstance) {
+            flash.message = "InventoryType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ inventoryTypeInstance : inventoryTypeInstance ] }
+    }
+
+    def delete = {
+        def inventoryTypeInstance = InventoryType.get( params.id )
+        if(inventoryTypeInstance) {
+            try {
+                inventoryTypeInstance.delete(flush:true)
+                flash.message = "InventoryType ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "InventoryType ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "InventoryType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def inventoryTypeInstance = InventoryType.get( params.id )
+
+        if(!inventoryTypeInstance) {
+            flash.message = "InventoryType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ inventoryTypeInstance : inventoryTypeInstance ]
+        }
+    }
+
+    def update = {
+        def inventoryTypeInstance = InventoryType.get( params.id )
+        if(inventoryTypeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(inventoryTypeInstance.version > version) {
+                    
+                    inventoryTypeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[inventoryTypeInstance:inventoryTypeInstance])
+                    return
+                }
+            }
+            inventoryTypeInstance.properties = params
+            if(!inventoryTypeInstance.hasErrors() && inventoryTypeInstance.save(flush: true)) {
+                flash.message = "InventoryType ${params.id} updated"
+                redirect(action:show,id:inventoryTypeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[inventoryTypeInstance:inventoryTypeInstance])
+            }
+        }
+        else {
+            flash.message = "InventoryType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def inventoryTypeInstance = new InventoryType()
+        inventoryTypeInstance.properties = params
+        return ['inventoryTypeInstance':inventoryTypeInstance]
+    }
+
+    def save = {
+        def inventoryTypeInstance = new InventoryType(params)
+        if(!inventoryTypeInstance.hasErrors() && inventoryTypeInstance.save(flush: true)) {
+            flash.message = "InventoryType ${inventoryTypeInstance.id} created"
+            redirect(action:show,id:inventoryTypeInstance.id)
+        }
+        else {
+            render(view:'create',model:[inventoryTypeInstance:inventoryTypeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/LoginController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/LoginController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/LoginController.groovy	(revision 753)
@@ -0,0 +1,188 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.RedirectUtils
+import org.grails.plugins.springsecurity.service.AuthenticateService
+
+import org.springframework.security.AuthenticationTrustResolverImpl
+import org.springframework.security.DisabledException
+import org.springframework.security.context.SecurityContextHolder as SCH
+import org.springframework.security.ui.AbstractProcessingFilter
+import org.springframework.security.ui.webapp.AuthenticationProcessingFilter
+
+/**
+ * Login Controller (Example).
+ */
+class LoginController {
+
+    /**
+    * Dependency injection for the authentication service.
+    */
+    def authenticateService
+
+    /**
+        * Dependency injection for OpenIDConsumer.
+        */
+    def openIDConsumer
+
+    /**
+    * Dependency injection for OpenIDAuthenticationProcessingFilter.
+    */
+    def openIDAuthenticationProcessingFilter
+
+    private final authenticationTrustResolver = new AuthenticationTrustResolverImpl()
+
+    def index = {
+        if (isLoggedIn()) {
+            redirect uri: '/'
+        }
+        else {
+            redirect action: auth, params: params
+        }
+    }
+
+    def loggedOut = {
+        flash['message'] = 'Successfully logged out'
+        auth()
+    }
+
+    /**
+    * Show the login page.
+    */
+    def auth = {
+
+        nocache(response)
+
+        if (isLoggedIn()) {
+            redirect uri: '/'
+            return
+        }
+
+        String view
+        String postUrl
+        def config = authenticateService.securityConfig.security
+        if (config.useOpenId) {
+            view = 'openIdAuth'
+            postUrl = "${request.contextPath}/login/openIdAuthenticate"
+        }
+        else if (config.useFacebook) {
+            view = 'facebookAuth'
+            postUrl = "${request.contextPath}${config.facebook.filterProcessesUrl}"
+        }
+        else {
+            view = 'auth'
+            postUrl = "${request.contextPath}${config.filterProcessesUrl}"
+        }
+
+        render view: view, model: [postUrl: postUrl]
+    }
+
+    /**
+    * Form submit action to start an OpenID authentication.
+    */
+    def openIdAuthenticate = {
+        String openID = params['j_username']
+        try {
+            String returnToURL = RedirectUtils.buildRedirectUrl(
+                    request, response, openIDAuthenticationProcessingFilter.filterProcessesUrl)
+            String redirectUrl = openIDConsumer.beginConsumption(request, openID, returnToURL)
+            redirect url: redirectUrl
+        }
+        catch (org.springframework.security.ui.openid.OpenIDConsumerException e) {
+            log.error "Consumer error: $e.message", e
+            redirect url: openIDAuthenticationProcessingFilter.authenticationFailureUrl
+        }
+    }
+
+    // Login page (function|json) for Ajax access.
+    def authAjax = {
+        nocache(response)
+        //this is example:
+        render """
+        <script type='text/javascript'>
+        (function() {
+            loginForm();
+        })();
+        </script>
+        """
+    }
+
+    /**
+    * The Ajax success redirect url.
+    */
+    def ajaxSuccess = {
+        nocache(response)
+        render '{success: true}'
+    }
+
+    /**
+    * Show denied page.
+    */
+    def denied = {
+        if (isLoggedIn() && authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) {
+            // have cookie but the page is guarded with IS_AUTHENTICATED_FULLY
+            redirect action: full, params: params
+        }
+    }
+
+    /**
+    * Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page.
+    */
+    def full = {
+        render view: 'auth', params: params,
+            model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication)]
+    }
+
+    // Denial page (data|view|json) for Ajax access.
+    def deniedAjax = {
+        //this is example:
+        render "{error: 'access denied'}"
+    }
+
+    /**
+    * login failed
+    */
+    def authfail = {
+
+        def username = session[AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY]
+        def msg = ''
+        def person = Person.findByLoginName(username)
+        def exception = session[AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY]
+        if (exception) {
+            if (exception instanceof DisabledException) {
+                msg = "[$username] is disabled."
+            }
+            else if (person?.authorities?.isEmpty()) {
+                msg = "[$username] has no granted authority."
+            }
+            else {
+                msg = "[$username] wrong username/password."
+            }
+        }
+
+        if (isAjax()) {
+            render "{error: '${msg}'}"
+        }
+        else {
+            flash.message = msg
+            redirect action: auth, params: params
+        }
+    }
+
+    /**
+    * Check if logged in.
+    */
+    private boolean isLoggedIn() {
+        return authenticateService.isLoggedIn()
+    }
+
+    private boolean isAjax() {
+        return authenticateService.isAjax(request)
+    }
+
+    /** cache controls */
+    private void nocache(response) {
+        response.setHeader('Cache-Control', 'no-cache') // HTTP 1.1
+        response.addDateHeader('Expires', 0)
+        response.setDateHeader('max-age', 0)
+        response.setIntHeader ('Expires', -1) //prevents caching at the proxy server
+        response.addHeader('cache-Control', 'private') //IE5.x only
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/LogoutController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/LogoutController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/LogoutController.groovy	(revision 753)
@@ -0,0 +1,14 @@
+/**
+ * Logout Controller (Example).
+ */
+class LogoutController {
+
+	/**
+	 * Index action. Redirects to the Spring security logout uri.
+	 */
+	def index = {
+		// TODO  put any pre-logout code here
+        
+		redirect(uri: '/j_spring_security_logout?logoutSuccessUrl=/login/loggedOut')
+	}
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/MaintenanceActionDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/MaintenanceActionDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/MaintenanceActionDetailedController.groovy	(revision 753)
@@ -0,0 +1,95 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class MaintenanceActionDetailedController extends BaseController {
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def show = {
+        def maintenanceActionInstance = MaintenanceAction.get( params.id )
+
+        if(!maintenanceActionInstance) {
+            flash.message = "MaintenanceAction not found with id ${params.id}"
+            redirect(controller: "appCore", action:"start")
+        }
+        else { return [ maintenanceActionInstance : maintenanceActionInstance ] }
+    }
+
+    def delete = {
+        def maintenanceActionInstance = MaintenanceAction.get( params.id )
+        if(maintenanceActionInstance) {
+            try {
+                def taskProcedure = maintenanceActionInstance.taskProcedure
+                maintenanceActionInstance.delete(flush:true)
+                flash.message = "MaintenanceAction ${params.id} deleted"
+                redirect(controller: "taskProcedureDetailed", action:"show", id:taskProcedure.id)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "MaintenanceAction ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "MaintenanceAction not found with id ${params.id}"
+            redirect(controller: "appCore", action:"start")
+        }
+    }
+
+    def edit = {
+        def maintenanceActionInstance = MaintenanceAction.get( params.id )
+
+        if(!maintenanceActionInstance) {
+            flash.message = "MaintenanceAction not found with id ${params.id}"
+            redirect(controller: "appCore", action:"start")
+        }
+        else {
+            return [ maintenanceActionInstance : maintenanceActionInstance ]
+        }
+    }
+
+    def update = {
+        def maintenanceActionInstance = MaintenanceAction.get( params.id )
+        if(maintenanceActionInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(maintenanceActionInstance.version > version) {
+                    
+                    maintenanceActionInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[maintenanceActionInstance:maintenanceActionInstance])
+                    return
+                }
+            }
+            maintenanceActionInstance.properties = params
+            if(!maintenanceActionInstance.hasErrors() && maintenanceActionInstance.save(flush: true)) {
+                flash.message = "MaintenanceAction ${params.id} updated"
+                redirect(action:show,id:maintenanceActionInstance.id)
+            }
+            else {
+                render(view:'edit',model:[maintenanceActionInstance:maintenanceActionInstance])
+            }
+        }
+        else {
+            flash.message = "MaintenanceAction not found with id ${params.id}"
+            redirect(controller: "appCore", action:"start")
+        }
+    }
+
+    def create = {
+        def maintenanceActionInstance = new MaintenanceAction()
+        maintenanceActionInstance.properties = params
+        return ['maintenanceActionInstance':maintenanceActionInstance]
+    }
+
+    def save = {
+        def maintenanceActionInstance = new MaintenanceAction(params)
+        if(!maintenanceActionInstance.hasErrors() && maintenanceActionInstance.save(flush: true)) {
+            flash.message = "MaintenanceAction ${maintenanceActionInstance.id} created"
+            redirect(action:show,id:maintenanceActionInstance.id)
+        }
+        else {
+            render(view:'create',model:[maintenanceActionInstance:maintenanceActionInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/MaintenancePolicyDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/MaintenancePolicyDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/MaintenancePolicyDetailedController.groovy	(revision 753)
@@ -0,0 +1,113 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class MaintenancePolicyDetailedController extends BaseController {
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ maintenancePolicyInstanceList: MaintenancePolicy.list( params ), maintenancePolicyInstanceTotal: MaintenancePolicy.count() ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def maintenancePolicyInstance = MaintenancePolicy.get( params.id )
+
+        if(!maintenancePolicyInstance) {
+            flash.message = "MaintenancePolicy not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ maintenancePolicyInstance : maintenancePolicyInstance ] }
+    }
+
+    def delete = {
+        def maintenancePolicyInstance = MaintenancePolicy.get( params.id )
+        if(maintenancePolicyInstance) {
+            try {
+                maintenancePolicyInstance.delete(flush:true)
+                flash.message = "MaintenancePolicy ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "MaintenancePolicy ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "MaintenancePolicy not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def maintenancePolicyInstance = MaintenancePolicy.get( params.id )
+
+        if(!maintenancePolicyInstance) {
+            flash.message = "MaintenancePolicy not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ maintenancePolicyInstance : maintenancePolicyInstance ]
+        }
+    }
+
+    def update = {
+        def maintenancePolicyInstance = MaintenancePolicy.get( params.id )
+        if(maintenancePolicyInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(maintenancePolicyInstance.version > version) {
+                    
+                    maintenancePolicyInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[maintenancePolicyInstance:maintenancePolicyInstance])
+                    return
+                }
+            }
+            maintenancePolicyInstance.properties = params
+            if(!maintenancePolicyInstance.hasErrors() && maintenancePolicyInstance.save(flush: true)) {
+                flash.message = "MaintenancePolicy ${params.id} updated"
+                redirect(action:show,id:maintenancePolicyInstance.id)
+            }
+            else {
+                render(view:'edit',model:[maintenancePolicyInstance:maintenancePolicyInstance])
+            }
+        }
+        else {
+            flash.message = "MaintenancePolicy not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def maintenancePolicyInstance = new MaintenancePolicy()
+        maintenancePolicyInstance.properties = params
+        return ['maintenancePolicyInstance':maintenancePolicyInstance]
+    }
+
+    def save = {
+        def maintenancePolicyInstance = new MaintenancePolicy(params)
+        if(!maintenancePolicyInstance.hasErrors() && maintenancePolicyInstance.save(flush: true)) {
+            flash.message = "MaintenancePolicy ${maintenancePolicyInstance.id} created"
+            redirect(action:show,id:maintenancePolicyInstance.id)
+        }
+        else {
+            render(view:'create',model:[maintenancePolicyInstance:maintenancePolicyInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/PeriodController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/PeriodController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/PeriodController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class PeriodController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ periodInstanceList: Period.list( params ), periodInstanceTotal: Period.count() ]
+    }
+
+    def show = {
+        def periodInstance = Period.get( params.id )
+
+        if(!periodInstance) {
+            flash.message = "Period not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ periodInstance : periodInstance ] }
+    }
+
+    def delete = {
+        def periodInstance = Period.get( params.id )
+        if(periodInstance) {
+            try {
+                periodInstance.delete(flush:true)
+                flash.message = "Period ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "Period ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "Period not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def periodInstance = Period.get( params.id )
+
+        if(!periodInstance) {
+            flash.message = "Period not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ periodInstance : periodInstance ]
+        }
+    }
+
+    def update = {
+        def periodInstance = Period.get( params.id )
+        if(periodInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(periodInstance.version > version) {
+                    
+                    periodInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[periodInstance:periodInstance])
+                    return
+                }
+            }
+            periodInstance.properties = params
+            if(!periodInstance.hasErrors() && periodInstance.save(flush: true)) {
+                flash.message = "Period ${params.id} updated"
+                redirect(action:show,id:periodInstance.id)
+            }
+            else {
+                render(view:'edit',model:[periodInstance:periodInstance])
+            }
+        }
+        else {
+            flash.message = "Period not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def periodInstance = new Period()
+        periodInstance.properties = params
+        return ['periodInstance':periodInstance]
+    }
+
+    def save = {
+        def periodInstance = new Period(params)
+        if(!periodInstance.hasErrors() && periodInstance.save(flush: true)) {
+            flash.message = "Period ${periodInstance.id} created"
+            redirect(action:show,id:periodInstance.id)
+        }
+        else {
+            render(view:'create',model:[periodInstance:periodInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/PersonController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/PersonController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/PersonController.groovy	(revision 753)
@@ -0,0 +1,282 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
+class PersonController extends BaseAppAdminController {
+
+    def filterService
+    def personCsvService
+    def authenticateService
+
+    // the delete, save and update actions only accept POST requests
+    static Map allowedMethods = [delete: 'POST', save: 'POST', update: 'POST']
+
+    def index = {
+        redirect action: list, params: params
+    }
+
+    /**
+    * Disaply the import view.
+    */
+    def importPersons = {
+    }
+
+    /**
+    * Handle the import save.
+    */
+    def importPersonsSave = {
+        def result = personCsvService.importPersons(request)
+
+        if(!result.error) {
+            response.contentType = ConfigurationHolder.config.grails.mime.types["text"]
+            response.setHeader("Content-disposition", "attachment; filename=LoginNamesAndPasswords.txt")
+            render result.loginNamesAndPasswords
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: importPersons)
+    }
+
+    /**
+    * Export a csv template.
+    * NOTE: IE has a 'validating' bug in dev mode that causes the export to take a long time!
+    * This does not appear to be a problem once deployed to Tomcat.
+    */
+    def exportPersonsTemplate = {
+        response.contentType = ConfigurationHolder.config.grails.mime.types["csv"]
+        response.setHeader("Content-disposition", "attachment; filename=personsTemplate.csv")
+        def s = personCsvService.buildPersonsTemplate()
+        render s
+    }
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100 )
+
+        if(!params.filter) {
+            return [personList: Person.list(params),
+                            personTotal: Person.count(),
+                            filterParams: params]
+        }
+
+        // filterPane:
+        return[ personList: filterService.filter( params, Person ),
+            personTotal: filterService.count( params, Person ),
+            filterParams: com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params),
+            params:params ]
+    }
+
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def person = Person.get(params.id)
+        if (!person) {
+            flash.message = "Person not found with id $params.id"
+            redirect action: list
+            return
+        }
+        def authorityList = person.authorities.sort { p1, p2 -> p1.id <=> p2.id }
+        [person: person, authorityList: authorityList]
+    }
+
+    /**
+    * Person delete action. Before removing an existing person,
+    * they should be removed from those authorities which they are involved.
+    */
+    def delete = {
+
+        def person = Person.get(params.id)
+        if (person) {
+            def authPrincipal = authenticateService.principal()
+            // Avoid self-delete.
+            if (!(authPrincipal instanceof String) && authPrincipal.username == person.loginName) {
+                flash.errorMessage = "You cannot delete yourself, please login as another manager and try again."
+                redirect(action:show,id:params.id)
+            }
+            else if ( person.id == 1L) {
+                flash.errorMessage = "You cannot delete the pseudo system person."
+                redirect(action:show,id:params.id)
+            }
+            else if ( person.id == 2L) {
+                flash.errorMessage = "You cannot delete the admin person."
+                redirect(action:show,id:params.id)
+            }
+            else {
+                //first, delete this person from Persons_Authorities table.
+                Authority.findAll().each { it.removeFromPersons(person) }
+                person.isActive = false
+                person.save(flush: true)
+
+                try {
+                    person.delete(flush: true)
+                    flash.message = "Person $params.id deleted."
+                    redirect(action:list)
+                }
+                catch(org.springframework.dao.DataIntegrityViolationException e) {
+                    flash.message = "Could not delete '$person.loginName' due to database constraints, but all authorities have been removed."
+                    redirect(action:show,id:params.id)
+                }
+            }
+        }
+        else {
+            flash.errorMessage = "Person not found with id $params.id"
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def person = Person.get(params.id)
+        if (!person) {
+            flash.message = "Person not found with id $params.id"
+            redirect action: list
+            return
+        }
+
+        if ( person.id == 1L) {
+            flash.errorMessage = "You cannot edit the pseudo system person."
+            redirect(action:show,id:params.id)
+            return
+        }
+
+        params.message = "To allow login at least the 'ROLE_AppUser' authority must be given."
+        return buildPersonModel(person)
+    }
+
+    /**
+    * Person update action.
+    */
+    def update = {
+        Person.withTransaction { status ->
+
+            def person = Person.get(params.id)
+            if (!person) {
+                flash.message = "Person not found with id $params.id"
+                redirect action: edit, id: params.id
+                return
+            }
+
+            long version = params.version.toLong()
+            if (person.version > version) {
+                person.errors.rejectValue 'version', "default.optimistic.locking.failure"
+                render view: 'edit', model: buildPersonModel(person)
+                return
+            }
+
+            if ( person.id == 1L) {
+                flash.errorMessage = "You cannot edit the pseudo system person."
+                redirect(action:show,id:params.id)
+                return
+            }
+
+            person.properties = params
+            person.setPersonGroupsFromCheckBoxList(params.personGroups)
+            person.setPurchasingGroupsFromCheckBoxList(params.purchasingGroups)
+
+            if(params.pass == "") {
+                person.pass = "InsertNothingToClearValidation"
+            }
+            else {
+                if (person.validate()) {
+                    person.password = authenticateService.encodePassword(params.pass)
+                }
+            }
+
+            if (!person.hasErrors() && person.save(flush: true)) {
+                addRemoveAuthorities(person)
+                flash.message = "Person '$params.id - $params.loginName' updated."
+                redirect action: show, id: person.id
+            }
+            else {
+                render view: 'edit', model: buildPersonModel(person)
+            }
+
+        } //end withTransaction
+    } // update()
+
+    def create = {
+        params.message = "To allow login at least the 'ROLE_AppUser' authority must be given."
+        [person: new Person(params), authorityList: getLimitedAuthorityList()]
+    }
+
+    /**
+    * Person save action.
+    */
+    def save = {
+        Person.withTransaction { status ->
+
+            def person = new Person()
+            person.properties = params
+            person.password = authenticateService.encodePassword(params.pass)
+            person.setPersonGroupsFromCheckBoxList(params.personGroups)
+            person.setPurchasingGroupsFromCheckBoxList(params.purchasingGroups)
+            if (person.save(flush: true)) {
+                addRemoveAuthorities(person)
+                redirect action: show, id: person.id
+            }
+            else {
+                render view: 'create', model: [person: person, authorityList: getLimitedAuthorityList()]
+            }
+
+        } //end withTransaction
+    }
+
+    /**
+    * Add or remove authorities from person as indicated in params.
+    */
+    private void addRemoveAuthorities(person) {
+        def authMap = [:]
+
+        // Build authMap from params.
+        for (key in params.keySet()) {
+            if(key.startsWith("ROLE")) {
+                authMap.(key.toString()) = "add"
+            }
+            else if(key.startsWith("_ROLE")) {
+                if( !authMap.(key.substring(1)) ) authMap.(key.substring(1)) = "remove"
+            }
+        }
+
+        // Add or remove authorities.
+        for(a in authMap) {
+            if(a.value == "add")
+                Authority.findByAuthority(a.key.toString()).addToPersons(person)
+            else
+                Authority.findByAuthority(a.key.toString()).removeFromPersons(person)
+        }
+    }
+
+    private Map buildPersonModel(person) {
+
+        List roles = getLimitedAuthorityList()
+        Set userRoleNames = []
+        for (role in person.authorities) {
+            userRoleNames << role.authority
+        }
+        LinkedHashMap<Authority, Boolean> roleMap = [:]
+        for (role in roles) {
+            roleMap[(role)] = userRoleNames.contains(role.authority)
+        }
+
+        return [person: person, roleMap: roleMap]
+    }
+
+    /**
+    * Get the full authorityList if current user is an App Admin else leave that authority off the list.
+    */
+    private List getLimitedAuthorityList() {
+        def authorityList = []
+        if(authenticateService.ifAnyGranted('ROLE_AppAdmin'))
+            authorityList = Authority.list().sort { p1, p2 -> p1.id <=> p2.id }
+        else
+            authorityList = Authority.withCriteria { gt("id", 1L) }.sort { p1, p2 -> p1.id <=> p2.id }
+
+        return authorityList
+    }
+} // end class
Index: branches/features/taskProcedureRework/grails-app/controllers/PersonGroupDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/PersonGroupDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/PersonGroupDetailedController.groovy	(revision 753)
@@ -0,0 +1,100 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
+class PersonGroupDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ personGroupInstanceList: PersonGroup.list( params ), personGroupInstanceTotal: PersonGroup.count() ]
+    }
+
+    def show = {
+        def personGroupInstance = PersonGroup.get( params.id )
+
+        if(!personGroupInstance) {
+            flash.message = "PersonGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ personGroupInstance : personGroupInstance ] }
+    }
+
+    def delete = {
+        def personGroupInstance = PersonGroup.get( params.id )
+        if(personGroupInstance) {
+            try {
+                personGroupInstance.delete(flush:true)
+                flash.message = "PersonGroup ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "PersonGroup ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "PersonGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def personGroupInstance = PersonGroup.get( params.id )
+
+        if(!personGroupInstance) {
+            flash.message = "PersonGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ personGroupInstance : personGroupInstance ]
+        }
+    }
+
+    def update = {
+        def personGroupInstance = PersonGroup.get( params.id )
+        if(personGroupInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(personGroupInstance.version > version) {
+                    
+                    personGroupInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[personGroupInstance:personGroupInstance])
+                    return
+                }
+            }
+            personGroupInstance.properties = params
+            if(!personGroupInstance.hasErrors() && personGroupInstance.save(flush: true)) {
+                flash.message = "PersonGroup ${params.id} updated"
+                redirect(action:show,id:personGroupInstance.id)
+            }
+            else {
+                render(view:'edit',model:[personGroupInstance:personGroupInstance])
+            }
+        }
+        else {
+            flash.message = "PersonGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def personGroupInstance = new PersonGroup()
+        personGroupInstance.properties = params
+        return ['personGroupInstance':personGroupInstance]
+    }
+
+    def save = {
+        def personGroupInstance = new PersonGroup(params)
+        if(!personGroupInstance.hasErrors() && personGroupInstance.save(flush: true)) {
+            flash.message = "PersonGroup ${personGroupInstance.id} created"
+            redirect(action:show,id:personGroupInstance.id)
+        }
+        else {
+            render(view:'create',model:[personGroupInstance:personGroupInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/PersonGroupTypeDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/PersonGroupTypeDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/PersonGroupTypeDetailedController.groovy	(revision 753)
@@ -0,0 +1,100 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
+class PersonGroupTypeDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ personGroupTypeInstanceList: PersonGroupType.list( params ), personGroupTypeInstanceTotal: PersonGroupType.count() ]
+    }
+
+    def show = {
+        def personGroupTypeInstance = PersonGroupType.get( params.id )
+
+        if(!personGroupTypeInstance) {
+            flash.message = "PersonGroupType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ personGroupTypeInstance : personGroupTypeInstance ] }
+    }
+
+    def delete = {
+        def personGroupTypeInstance = PersonGroupType.get( params.id )
+        if(personGroupTypeInstance) {
+            try {
+                personGroupTypeInstance.delete(flush:true)
+                flash.message = "PersonGroupType ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "PersonGroupType ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "PersonGroupType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def personGroupTypeInstance = PersonGroupType.get( params.id )
+
+        if(!personGroupTypeInstance) {
+            flash.message = "PersonGroupType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ personGroupTypeInstance : personGroupTypeInstance ]
+        }
+    }
+
+    def update = {
+        def personGroupTypeInstance = PersonGroupType.get( params.id )
+        if(personGroupTypeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(personGroupTypeInstance.version > version) {
+                    
+                    personGroupTypeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[personGroupTypeInstance:personGroupTypeInstance])
+                    return
+                }
+            }
+            personGroupTypeInstance.properties = params
+            if(!personGroupTypeInstance.hasErrors() && personGroupTypeInstance.save(flush: true)) {
+                flash.message = "PersonGroupType ${params.id} updated"
+                redirect(action:show,id:personGroupTypeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[personGroupTypeInstance:personGroupTypeInstance])
+            }
+        }
+        else {
+            flash.message = "PersonGroupType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def personGroupTypeInstance = new PersonGroupType()
+        personGroupTypeInstance.properties = params
+        return ['personGroupTypeInstance':personGroupTypeInstance]
+    }
+
+    def save = {
+        def personGroupTypeInstance = new PersonGroupType(params)
+        if(!personGroupTypeInstance.hasErrors() && personGroupTypeInstance.save(flush: true)) {
+            flash.message = "PersonGroupType ${personGroupTypeInstance.id} created"
+            redirect(action:show,id:personGroupTypeInstance.id)
+        }
+        else {
+            render(view:'create',model:[personGroupTypeInstance:personGroupTypeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/PictureDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/PictureDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/PictureDetailedController.groovy	(revision 753)
@@ -0,0 +1,215 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
+class PictureDetailedController extends BaseController {
+
+    def index = { redirect(action:list, params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        prepareList()
+        [ list: Picture.list(params), paginateCount: Picture.count() ]
+    }
+
+    void prepareList() {
+        if (!params.max) {
+            params.max = 10
+        }
+        if (!params.order) {
+            params.order = "desc"
+        }
+        if (!params.sort) {
+            params.sort = "id"
+        }
+    }
+
+    def show = {
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def picture = Picture.get( params.id )
+
+        if(!picture) {
+            flash.message = "Picture not found."
+            redirect(action:list)
+        }
+        else { [ picture : picture ] }
+    }
+
+    def delete = {
+        def picture = Picture.get(params.id)
+        def inventoryItem = InventoryItem.get(picture?.inventoryItem?.id)
+
+        if (inventoryItem && picture) {
+            Picture.withTransaction { status ->
+                inventoryItem.picture = null
+                inventoryItem.save()
+                picture.delete()
+            }
+            flash.message = "Picture ${params.id} deleted"
+            redirect(controller: "inventoryItemDetailed", action: show, id: inventoryItem.id)
+
+        }
+        else {
+            if(picture) {
+                flash.message = "Removing orphan picture ${picture.id}."
+                picture.delete(flush:true)
+                redirect(action: list)
+            }
+            else {
+                flash.message = "Picture not found"
+                redirect(action: list)
+            }
+        }
+    }
+
+    def edit = {
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def picture = Picture.get(params.id)
+        if (!picture) {
+            flash.message = "Picture not found"
+            redirect(action: list)
+        }
+        else {
+            [ picture : picture ]
+        }
+    }
+
+    def update = {
+        def picture = Picture.get(params.id)
+        def inventoryItem = picture?.inventoryItem
+        if (inventoryItem && picture) {
+
+            if(params.version) {
+                def version = params.version.toLong()
+                if(picture.version > version) {
+                    picture.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[picture:picture])
+                    return
+                }
+            }
+
+            picture.properties = params
+            if (!picture.hasErrors()) {
+                def imaging = new Imaging()
+                def images = imaging.updateAll(picture)
+                boolean result = false
+                Picture.withTransaction{ status ->
+                    result = picture.save()
+                }
+                if (result) {
+                    flash.message = "Picture ${params.id} updated"
+                    redirect(action: show, id: picture.id)
+                }
+                else {
+                    render(view: 'edit', model: [ picture: picture ])
+                }
+            }
+            else {
+                render(view: 'edit', model: [ picture: picture ])
+            }
+        }
+        else {
+            flash.message = "Picture not updated, picture or inventory item not found."
+            redirect(action: list)
+        }
+    }
+
+    def create = {
+        if(!params.inventoryItem?.id) {
+            flash.message = "Please select an inventory item and then 'Add Picture'."
+            redirect(controller: "inventoryItemDetailed", action: 'search')
+            return
+        }
+        def picture = new Picture()
+        picture.properties = params
+        [ picture: picture ]
+    }
+
+    def save = {
+        def inventoryItem = InventoryItem.get(params.inventoryItem.id)
+        if (inventoryItem) {
+            if(inventoryItem.picture) {
+                flash.message = "Inventory item already has a picture, please delete the old picture first."
+                redirect(controller: 'inventoryItemDetailed', action: 'show', id: inventoryItem.id)
+                return
+            }
+            def picture = new Picture(params)
+            def multiPartFile = request.getFile('file')
+            def imaging = new Imaging()
+            def images = null
+            if (multiPartFile && !multiPartFile.isEmpty()) {
+                if (multiPartFile.getSize() > Image.MAX_SIZE) {
+                    picture.errors.rejectValue('file', 'picture.file.maxSize.exceeded',
+                        [ 'file', 'Picture', Image.MAX_SIZE ] as Object[],
+                        'Property [{0}] of class [{1}] image file is too big (maximum [{2}] bytes)')
+                }
+                else {
+                    try {
+                        images = imaging.createAll(inventoryItem, picture, multiPartFile.inputStream)
+                    }
+                    catch(Exception ex) {
+                        log.error("picture save", ex)
+                        picture.errors.rejectValue('file', 'picture.file.unrecognised',
+                            [ 'file', 'Picture', multiPartFile.originalFilename ] as Object[],
+                            'Property [{0}] of class [{1}] image file [{2}]: type not recognised')
+                    }
+                }
+            }
+            else {
+                picture.errors.rejectValue('file', 'picture.file.missing',
+                    ['file', 'Picture', ''] as Object[],
+                    'Property [{0}] of class [{1}] no file specified')
+            }
+            if (images && !picture.hasErrors()) {
+                boolean result = false
+                Picture.withTransaction { status ->
+                    images.each { image ->
+                        picture.addToImages(image)
+                    }
+                    result = picture.save()
+                    inventoryItem.picture = picture
+                    inventoryItem.save()
+                }
+                if (result) {
+                    flash.message = "Picture ${picture.id} created"
+                    redirect(controller: 'inventoryItemDetailed', action: 'show', id: inventoryItem.id)
+                }
+                else {
+                    render(view: 'create', model: [ picture: picture ])
+                }
+            }
+            else {
+                render(view: 'create', model: [ picture: picture ])
+            }
+        }
+        else {
+            flash.message = "Picture not created, inventory item not found."
+            redirect(action: list)
+        }
+    }
+
+    def view = {
+        def picture = Picture.get(params.id)
+        def size = params.size ? Integer.parseInt(params.size) : Image.Small
+        def image = picture ? Image.findByPictureAndSize(picture, size) : null
+        if (picture && image) {
+            response.setContentType(image.contentType)
+            response.setContentLength(image.data.size())
+            response.setHeader('filename', image.filename())
+            OutputStream out = response.outputStream
+            out.write(image.data)
+            out.close()
+        }
+        else {
+            response.sendError(404)
+        }
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/ProductionReferenceDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/ProductionReferenceDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/ProductionReferenceDetailedController.groovy	(revision 753)
@@ -0,0 +1,100 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_ProductionManager'])
+class ProductionReferenceDetailedController extends BaseController {
+
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ productionReferenceInstanceList: ProductionReference.list( params ), productionReferenceInstanceTotal: ProductionReference.count() ]
+    }
+
+    def show = {
+        def productionReferenceInstance = ProductionReference.get( params.id )
+
+        if(!productionReferenceInstance) {
+            flash.message = "ProductionReference not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ productionReferenceInstance : productionReferenceInstance ] }
+    }
+
+    def delete = {
+        def productionReferenceInstance = ProductionReference.get( params.id )
+        if(productionReferenceInstance) {
+            try {
+                productionReferenceInstance.delete(flush:true)
+                flash.message = "ProductionReference ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "ProductionReference ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "ProductionReference not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def productionReferenceInstance = ProductionReference.get( params.id )
+
+        if(!productionReferenceInstance) {
+            flash.message = "ProductionReference not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ productionReferenceInstance : productionReferenceInstance ]
+        }
+    }
+
+    def update = {
+        def productionReferenceInstance = ProductionReference.get( params.id )
+        if(productionReferenceInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(productionReferenceInstance.version > version) {
+                    
+                    productionReferenceInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[productionReferenceInstance:productionReferenceInstance])
+                    return
+                }
+            }
+            productionReferenceInstance.properties = params
+            if(!productionReferenceInstance.hasErrors() && productionReferenceInstance.save(flush: true)) {
+                flash.message = "ProductionReference ${params.id} updated"
+                redirect(action:show,id:productionReferenceInstance.id)
+            }
+            else {
+                render(view:'edit',model:[productionReferenceInstance:productionReferenceInstance])
+            }
+        }
+        else {
+            flash.message = "ProductionReference not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def productionReferenceInstance = new ProductionReference()
+        productionReferenceInstance.properties = params
+        return ['productionReferenceInstance':productionReferenceInstance]
+    }
+
+    def save = {
+        def productionReferenceInstance = new ProductionReference(params)
+        if(!productionReferenceInstance.hasErrors() && productionReferenceInstance.save(flush: true)) {
+            flash.message = "ProductionReference ${productionReferenceInstance.id} created"
+            redirect(action:show,id:productionReferenceInstance.id)
+        }
+        else {
+            render(view:'create',model:[productionReferenceInstance:productionReferenceInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/PurchasingGroupDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/PurchasingGroupDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/PurchasingGroupDetailedController.groovy	(revision 753)
@@ -0,0 +1,110 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
+class PurchasingGroupDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ purchasingGroupInstanceList: PurchasingGroup.list( params ), purchasingGroupInstanceTotal: PurchasingGroup.count() ]
+    }
+
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def purchasingGroupInstance = PurchasingGroup.get( params.id )
+
+        if(!purchasingGroupInstance) {
+            flash.message = "PurchasingGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ purchasingGroupInstance : purchasingGroupInstance ] }
+    }
+
+    def delete = {
+        def purchasingGroupInstance = PurchasingGroup.get( params.id )
+        if(purchasingGroupInstance) {
+            try {
+                purchasingGroupInstance.delete(flush:true)
+                flash.message = "PurchasingGroup ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "PurchasingGroup ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "PurchasingGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def purchasingGroupInstance = PurchasingGroup.get( params.id )
+
+        if(!purchasingGroupInstance) {
+            flash.message = "PurchasingGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ purchasingGroupInstance : purchasingGroupInstance ]
+        }
+    }
+
+    def update = {
+        def purchasingGroupInstance = PurchasingGroup.get( params.id )
+        if(purchasingGroupInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(purchasingGroupInstance.version > version) {
+                    
+                    purchasingGroupInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[purchasingGroupInstance:purchasingGroupInstance])
+                    return
+                }
+            }
+            purchasingGroupInstance.properties = params
+            if(!purchasingGroupInstance.hasErrors() && purchasingGroupInstance.save(flush: true)) {
+                flash.message = "PurchasingGroup ${params.id} updated"
+                redirect(action:show,id:purchasingGroupInstance.id)
+            }
+            else {
+                render(view:'edit',model:[purchasingGroupInstance:purchasingGroupInstance])
+            }
+        }
+        else {
+            flash.message = "PurchasingGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def purchasingGroupInstance = new PurchasingGroup()
+        purchasingGroupInstance.properties = params
+        return ['purchasingGroupInstance':purchasingGroupInstance]
+    }
+
+    def save = {
+        def purchasingGroupInstance = new PurchasingGroup(params)
+        if(!purchasingGroupInstance.hasErrors() && purchasingGroupInstance.save(flush: true)) {
+            flash.message = "PurchasingGroup ${purchasingGroupInstance.id} created"
+            redirect(action:show,id:purchasingGroupInstance.id)
+        }
+        else {
+            render(view:'create',model:[purchasingGroupInstance:purchasingGroupInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/ReportController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/ReportController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/ReportController.groovy	(revision 753)
@@ -0,0 +1,316 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+import org.springframework.web.servlet.support.RequestContextUtils as RCU
+
+class ReportController extends BaseController {
+
+    def authService
+    def dateUtilService
+    def taskReportService
+    def assetReportService
+    def inventoryReportService
+
+    def index = { redirect(action:templatePortrait,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    //static allowedMethods = [list:'POST']
+
+    def templatePortrait = {
+
+        params.startDate = new Date()
+        params.endDate = new Date()
+
+        params.reportTitle = "Template Report (Portrait)"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+        params.startDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: params.startDate)
+        params.endDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: params.endDate)
+
+        def dataModel = createTemplateData()
+
+        // Jasper plugin controller expects data to be a Collection.
+        chain(controller:'jasper', action:'index', model:[data: [dataModel]], params:params)
+
+    } // templatePortrait
+
+    def templateLandscape = {
+
+        params.startDate = new Date()
+        params.endDate = new Date()
+
+        params.reportTitle = "Template Report (Landscape)"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+        params.startDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: params.startDate)
+        params.endDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: params.endDate)
+
+        def dataModel = createTemplateData()
+
+        // Jasper plugin controller expects data to be a Collection.
+        chain(controller:'jasper', action:'index', model:[data: [dataModel]], params:params)
+
+    } // templateLandscape
+
+    private createTemplateData() {
+
+        def result = [:]
+        result.summaryOfCalculationMethod = "Summary string of the calculations performed."
+        result.dataList = []
+        for(i in 1..5) {
+            def dataDetails = [:]
+            dataDetails.description = "Data description " + i.toString()
+            result.dataList << dataDetails
+        }
+
+        // Success.
+        return result
+
+    } // createTemplateData
+
+    def downloadTemplate = {
+
+        // params.fileName is not used directly to negate any security issues..
+        def fileName = (params.fileName == 'templateLandscape.jrxml') ? 'templateLandscape.jrxml' : 'templatePortrait.jrxml'
+        def f = grailsApplication.mainContext.getResource("reports/${fileName}").getFile()
+        if(f.isFile()) {
+            response.contentType = ConfigurationHolder.config.grails.mime.types["text"]
+            response.setHeader("Content-disposition", "attachment; filename=${fileName}")
+            render f.text
+        }
+        else
+            render(status:404, text: "File Not Found: ${f}")
+
+    } // downLoadTemplate
+
+    def reactiveRatio = {
+
+        def result = taskReportService.getReactiveRatio(params, RCU.getLocale(request))
+
+        params.reportTitle = "Reactive Ratio Report"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+        params.startDateString = result.startDateString
+        params.endDateString = result.endDateString
+
+        if(!result.error) {
+            // Jasper plugin controller expects data to be a Collection.
+            chain(controller:'jasper', action:'index', model:[data: [result]], params:params)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(controller: 'appCore', action: 'start', params: [showTab:'showReportsTab'])
+
+    } // reactiveRatio
+
+    def immediateCallouts = {
+
+        def result = taskReportService.getImmediateCallouts(params, RCU.getLocale(request))
+
+        params.reportTitle = "Immediate Callouts"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+        params.startDateString = result.startDateString
+        params.endDateString = result.endDateString
+
+        if(!result.error) {
+            // Jasper plugin controller expects data to be a Collection.
+            chain(controller:'jasper', action:'index', model:[data: [result]], params:params)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(controller: 'appCore', action: 'start', params: [showTab:'showReportsTab'])
+
+    } // immediateCallouts
+
+    def stockTakeOverview = {
+
+        params.reportTitle = "Stock Take Overview"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+
+        def dataModel = inventoryReportService.getStockTakeOverview(params, RCU.getLocale(request))
+
+        // Jasper plugin controller expects data to be a Collection.
+        chain(controller:'jasper', action:'index', model:[data: [dataModel]], params:params)
+
+    } // stockTakeOverview
+
+    def stockTakeByLocation = {
+
+        params.reportTitle = "Stock Take By Location"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+
+        def dataModel = inventoryReportService.getStockTakeByLocation(params, RCU.getLocale(request))
+
+        // Jasper plugin controller expects data to be a Collection.
+        chain(controller:'jasper', action:'index', model:[data: [dataModel]], params:params)
+
+    } // stockTakeByLocation
+
+    def assetDetail = {
+
+        params.reportTitle = "Asset Detail"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+        if(params.section.id == 'all') {
+            params.section = "All"
+            params.site = "All"
+        }
+        else {
+            params.section = Section.get(params.section.id.toLong())
+            params.site = params.section.site
+        }
+
+        def dataModel = assetReportService.getAssetDetail(params, RCU.getLocale(request))
+
+        // Jasper plugin controller expects data to be a Collection.
+        chain(controller:'jasper', action:'index', model:[data: dataModel], params:params)
+
+    } // assetDetail
+
+    def assetRegister = {
+
+        params.reportTitle = "Asset Register"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+
+        def dataModel = assetReportService.getAssetRegister(params, RCU.getLocale(request))
+
+        // Jasper plugin controller expects data to be a Collection.
+        chain(controller:'jasper', action:'index', model:[data: [dataModel]], params:params)
+
+    } // assetRegister
+
+    def equipmentRegisterOhsGsp = {
+        render(view: 'equipmentRegisterOhs')
+    }
+
+    def equipmentRegisterOhs = {
+
+        params.calculateRegulatoryTaskCompletion = true
+        def result = assetReportService.getEquipmentRegister(params, RCU.getLocale(request))
+
+        params.reportTitle = "Equipment Register OH&S"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+        params.startDateString = result.startDateString
+        params.endDateString = result.endDateString
+
+        if(!result.error) {
+            // Jasper plugin controller expects data to be a Collection.
+            chain(controller:'jasper', action:'index', model:[data: [result]], params:params)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: 'equipmentRegisterOhsGsp')
+
+//         render {
+//             dataModel.dataList.each {
+//                 p("$it")
+//             }
+//         }
+
+    } // equipmentRegisterOhs
+
+    def equipmentRegisterFinancial = {
+
+        params.reportTitle = "Equipment Register Financial"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+
+        def dataModel = assetReportService.getEquipmentRegister(params, RCU.getLocale(request))
+
+        // Jasper plugin controller expects data to be a Collection.
+        chain(controller:'jasper', action:'index', model:[data: [dataModel]], params:params)
+
+    } // equipmentRegisterFinancial
+
+    def inventoryValueDetailedGsp = {
+        render(view: 'inventoryValueDetailed')
+    }
+
+    def inventoryValueDetailed = {
+
+        params.reportTitle = "Inventory Value Detailed"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+
+        def dataModel = inventoryReportService.getInventoryValueDetailed(params, RCU.getLocale(request))
+
+        // Jasper plugin controller expects data to be a Collection.
+        chain(controller:'jasper', action:'index', model:[data: [dataModel]], params:params)
+
+    }
+
+    def inventoryValueOverviewGsp = {
+        render(view: 'inventoryValueOverview')
+    }
+
+    def inventoryValueOverview = {
+
+        params.reportTitle = "Inventory Value Overview"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+
+        def dataModel = inventoryReportService.getInventoryValueOverview(params, RCU.getLocale(request))
+
+        // Jasper plugin controller expects data to be a Collection.
+        chain(controller:'jasper', action:'index', model:[data: [dataModel]], params:params)
+
+    }
+
+    def regulatoryRequirementsGsp = {
+        render(view: 'regulatoryRequirements')
+    }
+
+    def regulatoryRequirements = {
+
+        def result = assetReportService.getRegulatoryRequirements(params, RCU.getLocale(request))
+
+        params.reportTitle = "Asset Regulatory Requirements"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+        params.startDateString = result.startDateString
+        params.endDateString = result.endDateString
+
+        if(!result.error) {
+            // Jasper plugin controller expects data to be a Collection.
+            chain(controller:'jasper', action:'index', model:[data: [result]], params:params)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: 'regulatoryRequirementsGsp')
+
+    } // regulatoryRequirements
+
+    def mandatoryRequirementsGsp = {
+        render(view: 'mandatoryRequirements')
+    }
+
+    def mandatoryRequirements = {
+
+        def result = assetReportService.getMandatoryRequirements(params, RCU.getLocale(request))
+
+        params.reportTitle = "Asset Mandatory Requirements"
+        params.logoUrl = grailsApplication.mainContext.getResource('images/logo.png').getURL()
+        params.currentUser = authService.currentUser
+        params.startDateString = result.startDateString
+        params.endDateString = result.endDateString
+
+        if(!result.error) {
+            // Jasper plugin controller expects data to be a Collection.
+            chain(controller:'jasper', action:'index', model:[data: [result]], params:params)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+        redirect(action: 'mandatoryRequirementsGsp')
+
+    } // mandatoryRequirements
+
+} // end of class.
Index: branches/features/taskProcedureRework/grails-app/controllers/SectionDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/SectionDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/SectionDetailedController.groovy	(revision 753)
@@ -0,0 +1,116 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class SectionDetailedController extends BaseController {
+
+    def sectionService
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def index = { redirect(action:list,params:params) }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ sectionInstanceList: Section.list( params ), sectionInstanceTotal: Section.count() ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def sectionInstance = Section.get( params.id )
+
+        if(!sectionInstance) {
+            flash.message = "Section not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ sectionInstance : sectionInstance ] }
+    }
+
+    @Secured(['ROLE_AppAdmin'])
+    def delete = {
+        def result = sectionService.delete(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.delete.success", args: ["Section", params.id])
+            redirect(action:list)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.error.code == "default.not.found") {
+            redirect(action:list)
+            return
+        }
+
+        redirect(action:show, id: params.id)
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def sectionInstance = Section.get( params.id )
+
+        if(!sectionInstance) {
+            flash.message = "Section not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ sectionInstance : sectionInstance ]
+        }
+    }
+
+    def update = {
+        def sectionInstance = Section.get( params.id )
+        if(sectionInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(sectionInstance.version > version) {
+                    
+                    sectionInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[sectionInstance:sectionInstance])
+                    return
+                }
+            }
+            sectionInstance.properties = params
+            if(!sectionInstance.hasErrors() && sectionInstance.save(flush: true)) {
+                flash.message = "Section ${params.id} updated"
+                redirect(action:show,id:sectionInstance.id)
+            }
+            else {
+                render(view:'edit',model:[sectionInstance:sectionInstance])
+            }
+        }
+        else {
+            flash.message = "Section not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def sectionInstance = new Section()
+        sectionInstance.properties = params
+        return ['sectionInstance':sectionInstance]
+    }
+
+    def save = {
+        def sectionInstance = new Section(params)
+        if(!sectionInstance.hasErrors() && sectionInstance.save(flush: true)) {
+            flash.message = "Section ${sectionInstance.id} created"
+            redirect(action:show,id:sectionInstance.id)
+        }
+        else {
+            render(view:'create',model:[sectionInstance:sectionInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/SectionExtendedAttributeDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/SectionExtendedAttributeDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/SectionExtendedAttributeDetailedController.groovy	(revision 753)
@@ -0,0 +1,100 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class SectionExtendedAttributeDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ sectionExtendedAttributeInstanceList: SectionExtendedAttribute.list( params ), sectionExtendedAttributeInstanceTotal: SectionExtendedAttribute.count() ]
+    }
+
+    def show = {
+        def sectionExtendedAttributeInstance = SectionExtendedAttribute.get( params.id )
+
+        if(!sectionExtendedAttributeInstance) {
+            flash.message = "SectionExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ sectionExtendedAttributeInstance : sectionExtendedAttributeInstance ] }
+    }
+
+    def delete = {
+        def sectionExtendedAttributeInstance = SectionExtendedAttribute.get( params.id )
+        if(sectionExtendedAttributeInstance) {
+            try {
+                sectionExtendedAttributeInstance.delete(flush:true)
+                flash.message = "SectionExtendedAttribute ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "SectionExtendedAttribute ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "SectionExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def sectionExtendedAttributeInstance = SectionExtendedAttribute.get( params.id )
+
+        if(!sectionExtendedAttributeInstance) {
+            flash.message = "SectionExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ sectionExtendedAttributeInstance : sectionExtendedAttributeInstance ]
+        }
+    }
+
+    def update = {
+        def sectionExtendedAttributeInstance = SectionExtendedAttribute.get( params.id )
+        if(sectionExtendedAttributeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(sectionExtendedAttributeInstance.version > version) {
+                    
+                    sectionExtendedAttributeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[sectionExtendedAttributeInstance:sectionExtendedAttributeInstance])
+                    return
+                }
+            }
+            sectionExtendedAttributeInstance.properties = params
+            if(!sectionExtendedAttributeInstance.hasErrors() && sectionExtendedAttributeInstance.save(flush: true)) {
+                flash.message = "SectionExtendedAttribute ${params.id} updated"
+                redirect(action:show,id:sectionExtendedAttributeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[sectionExtendedAttributeInstance:sectionExtendedAttributeInstance])
+            }
+        }
+        else {
+            flash.message = "SectionExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def sectionExtendedAttributeInstance = new SectionExtendedAttribute()
+        sectionExtendedAttributeInstance.properties = params
+        return ['sectionExtendedAttributeInstance':sectionExtendedAttributeInstance]
+    }
+
+    def save = {
+        def sectionExtendedAttributeInstance = new SectionExtendedAttribute(params)
+        if(!sectionExtendedAttributeInstance.hasErrors() && sectionExtendedAttributeInstance.save(flush: true)) {
+            flash.message = "SectionExtendedAttribute ${sectionExtendedAttributeInstance.id} created"
+            redirect(action:show,id:sectionExtendedAttributeInstance.id)
+        }
+        else {
+            render(view:'create',model:[sectionExtendedAttributeInstance:sectionExtendedAttributeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/SiteDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/SiteDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/SiteDetailedController.groovy	(revision 753)
@@ -0,0 +1,116 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class SiteDetailedController extends BaseController {
+
+    def siteService
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def index = { redirect(action:list,params:params) }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ siteInstanceList: Site.list( params ), siteInstanceTotal: Site.count() ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def siteInstance = Site.get( params.id )
+
+        if(!siteInstance) {
+            flash.message = "Site not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ siteInstance : siteInstance ] }
+    }
+
+    @Secured(['ROLE_AppAdmin'])
+    def delete = {
+        def result = siteService.delete(params)
+
+        if(!result.error) {
+            flash.message = g.message(code: "default.delete.success", args: ["Site", params.id])
+            redirect(action:list)
+            return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.error.code == "default.not.found") {
+            redirect(action:list)
+            return
+        }
+
+        redirect(action:show, id: params.id)
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def siteInstance = Site.get( params.id )
+
+        if(!siteInstance) {
+            flash.message = "Site not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ siteInstance : siteInstance ]
+        }
+    }
+
+    def update = {
+        def siteInstance = Site.get( params.id )
+        if(siteInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(siteInstance.version > version) {
+                    
+                    siteInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[siteInstance:siteInstance])
+                    return
+                }
+            }
+            siteInstance.properties = params
+            if(!siteInstance.hasErrors() && siteInstance.save(flush: true)) {
+                flash.message = "Site ${params.id} updated"
+                redirect(action:show,id:siteInstance.id)
+            }
+            else {
+                render(view:'edit',model:[siteInstance:siteInstance])
+            }
+        }
+        else {
+            flash.message = "Site not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def siteInstance = new Site()
+        siteInstance.properties = params
+        return ['siteInstance':siteInstance]
+    }
+
+    def save = {
+        def siteInstance = new Site(params)
+        if(!siteInstance.hasErrors() && siteInstance.save(flush: true)) {
+            flash.message = "Site ${siteInstance.id} created"
+            redirect(action:show,id:siteInstance.id)
+        }
+        else {
+            render(view:'create',model:[siteInstance:siteInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/SiteExtendedAttributeDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/SiteExtendedAttributeDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/SiteExtendedAttributeDetailedController.groovy	(revision 753)
@@ -0,0 +1,100 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class SiteExtendedAttributeDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ siteExtendedAttributeInstanceList: SiteExtendedAttribute.list( params ), siteExtendedAttributeInstanceTotal: SiteExtendedAttribute.count() ]
+    }
+
+    def show = {
+        def siteExtendedAttributeInstance = SiteExtendedAttribute.get( params.id )
+
+        if(!siteExtendedAttributeInstance) {
+            flash.message = "SiteExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ siteExtendedAttributeInstance : siteExtendedAttributeInstance ] }
+    }
+
+    def delete = {
+        def siteExtendedAttributeInstance = SiteExtendedAttribute.get( params.id )
+        if(siteExtendedAttributeInstance) {
+            try {
+                siteExtendedAttributeInstance.delete(flush:true)
+                flash.message = "SiteExtendedAttribute ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "SiteExtendedAttribute ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "SiteExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def siteExtendedAttributeInstance = SiteExtendedAttribute.get( params.id )
+
+        if(!siteExtendedAttributeInstance) {
+            flash.message = "SiteExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ siteExtendedAttributeInstance : siteExtendedAttributeInstance ]
+        }
+    }
+
+    def update = {
+        def siteExtendedAttributeInstance = SiteExtendedAttribute.get( params.id )
+        if(siteExtendedAttributeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(siteExtendedAttributeInstance.version > version) {
+                    
+                    siteExtendedAttributeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[siteExtendedAttributeInstance:siteExtendedAttributeInstance])
+                    return
+                }
+            }
+            siteExtendedAttributeInstance.properties = params
+            if(!siteExtendedAttributeInstance.hasErrors() && siteExtendedAttributeInstance.save(flush: true)) {
+                flash.message = "SiteExtendedAttribute ${params.id} updated"
+                redirect(action:show,id:siteExtendedAttributeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[siteExtendedAttributeInstance:siteExtendedAttributeInstance])
+            }
+        }
+        else {
+            flash.message = "SiteExtendedAttribute not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def siteExtendedAttributeInstance = new SiteExtendedAttribute()
+        siteExtendedAttributeInstance.properties = params
+        return ['siteExtendedAttributeInstance':siteExtendedAttributeInstance]
+    }
+
+    def save = {
+        def siteExtendedAttributeInstance = new SiteExtendedAttribute(params)
+        if(!siteExtendedAttributeInstance.hasErrors() && siteExtendedAttributeInstance.save(flush: true)) {
+            flash.message = "SiteExtendedAttribute ${siteExtendedAttributeInstance.id} created"
+            redirect(action:show,id:siteExtendedAttributeInstance.id)
+        }
+        else {
+            render(view:'create',model:[siteExtendedAttributeInstance:siteExtendedAttributeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/SupplierDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/SupplierDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/SupplierDetailedController.groovy	(revision 753)
@@ -0,0 +1,110 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager'])
+class SupplierDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ supplierInstanceList: Supplier.list( params ), supplierInstanceTotal: Supplier.count() ]
+    }
+
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def supplierInstance = Supplier.get( params.id )
+
+        if(!supplierInstance) {
+            flash.message = "Supplier not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ supplierInstance : supplierInstance ] }
+    }
+
+    def delete = {
+        def supplierInstance = Supplier.get( params.id )
+        if(supplierInstance) {
+            try {
+                supplierInstance.delete(flush:true)
+                flash.message = "Supplier ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "Supplier ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "Supplier not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def supplierInstance = Supplier.get( params.id )
+
+        if(!supplierInstance) {
+            flash.message = "Supplier not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ supplierInstance : supplierInstance ]
+        }
+    }
+
+    def update = {
+        def supplierInstance = Supplier.get( params.id )
+        if(supplierInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(supplierInstance.version > version) {
+                    
+                    supplierInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[supplierInstance:supplierInstance])
+                    return
+                }
+            }
+            supplierInstance.properties = params
+            if(!supplierInstance.hasErrors() && supplierInstance.save(flush: true)) {
+                flash.message = "Supplier ${params.id} updated"
+                redirect(action:show,id:supplierInstance.id)
+            }
+            else {
+                render(view:'edit',model:[supplierInstance:supplierInstance])
+            }
+        }
+        else {
+            flash.message = "Supplier not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def supplierInstance = new Supplier()
+        supplierInstance.properties = params
+        return ['supplierInstance':supplierInstance]
+    }
+
+    def save = {
+        def supplierInstance = new Supplier(params)
+        if(!supplierInstance.hasErrors() && supplierInstance.save(flush: true)) {
+            flash.message = "Supplier ${supplierInstance.id} created"
+            redirect(action:show,id:supplierInstance.id)
+        }
+        else {
+            render(view:'create',model:[supplierInstance:supplierInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/SupplierTypeDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/SupplierTypeDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/SupplierTypeDetailedController.groovy	(revision 753)
@@ -0,0 +1,113 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager'])
+class SupplierTypeDetailedController extends BaseController {
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ supplierTypeInstanceList: SupplierType.list( params ), supplierTypeInstanceTotal: SupplierType.count() ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_AssetManager', 'ROLE_AssetUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def supplierTypeInstance = SupplierType.get( params.id )
+
+        if(!supplierTypeInstance) {
+            flash.message = "SupplierType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ supplierTypeInstance : supplierTypeInstance ] }
+    }
+
+    def delete = {
+        def supplierTypeInstance = SupplierType.get( params.id )
+        if(supplierTypeInstance) {
+            try {
+                supplierTypeInstance.delete(flush:true)
+                flash.message = "SupplierType ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "SupplierType ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "SupplierType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def supplierTypeInstance = SupplierType.get( params.id )
+
+        if(!supplierTypeInstance) {
+            flash.message = "SupplierType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ supplierTypeInstance : supplierTypeInstance ]
+        }
+    }
+
+    def update = {
+        def supplierTypeInstance = SupplierType.get( params.id )
+        if(supplierTypeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(supplierTypeInstance.version > version) {
+                    
+                    supplierTypeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[supplierTypeInstance:supplierTypeInstance])
+                    return
+                }
+            }
+            supplierTypeInstance.properties = params
+            if(!supplierTypeInstance.hasErrors() && supplierTypeInstance.save(flush: true)) {
+                flash.message = "SupplierType ${params.id} updated"
+                redirect(action:show,id:supplierTypeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[supplierTypeInstance:supplierTypeInstance])
+            }
+        }
+        else {
+            flash.message = "SupplierType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def supplierTypeInstance = new SupplierType()
+        supplierTypeInstance.properties = params
+        return ['supplierTypeInstance':supplierTypeInstance]
+    }
+
+    def save = {
+        def supplierTypeInstance = new SupplierType(params)
+        if(!supplierTypeInstance.hasErrors() && supplierTypeInstance.save(flush: true)) {
+            flash.message = "SupplierType ${supplierTypeInstance.id} created"
+            redirect(action:show,id:supplierTypeInstance.id)
+        }
+        else {
+            render(view:'create',model:[supplierTypeInstance:supplierTypeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/TaskBudgetStatusController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskBudgetStatusController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskBudgetStatusController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class TaskBudgetStatusController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ taskBudgetStatusInstanceList: TaskBudgetStatus.list( params ), taskBudgetStatusInstanceTotal: TaskBudgetStatus.count() ]
+    }
+
+    def show = {
+        def taskBudgetStatusInstance = TaskBudgetStatus.get( params.id )
+
+        if(!taskBudgetStatusInstance) {
+            flash.message = "TaskBudgetStatus not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ taskBudgetStatusInstance : taskBudgetStatusInstance ] }
+    }
+
+    def delete = {
+        def taskBudgetStatusInstance = TaskBudgetStatus.get( params.id )
+        if(taskBudgetStatusInstance) {
+            try {
+                taskBudgetStatusInstance.delete(flush:true)
+                flash.message = "TaskBudgetStatus ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "TaskBudgetStatus ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "TaskBudgetStatus not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def taskBudgetStatusInstance = TaskBudgetStatus.get( params.id )
+
+        if(!taskBudgetStatusInstance) {
+            flash.message = "TaskBudgetStatus not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ taskBudgetStatusInstance : taskBudgetStatusInstance ]
+        }
+    }
+
+    def update = {
+        def taskBudgetStatusInstance = TaskBudgetStatus.get( params.id )
+        if(taskBudgetStatusInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(taskBudgetStatusInstance.version > version) {
+                    
+                    taskBudgetStatusInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[taskBudgetStatusInstance:taskBudgetStatusInstance])
+                    return
+                }
+            }
+            taskBudgetStatusInstance.properties = params
+            if(!taskBudgetStatusInstance.hasErrors() && taskBudgetStatusInstance.save(flush: true)) {
+                flash.message = "TaskBudgetStatus ${params.id} updated"
+                redirect(action:show,id:taskBudgetStatusInstance.id)
+            }
+            else {
+                render(view:'edit',model:[taskBudgetStatusInstance:taskBudgetStatusInstance])
+            }
+        }
+        else {
+            flash.message = "TaskBudgetStatus not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def taskBudgetStatusInstance = new TaskBudgetStatus()
+        taskBudgetStatusInstance.properties = params
+        return ['taskBudgetStatusInstance':taskBudgetStatusInstance]
+    }
+
+    def save = {
+        def taskBudgetStatusInstance = new TaskBudgetStatus(params)
+        if(!taskBudgetStatusInstance.hasErrors() && taskBudgetStatusInstance.save(flush: true)) {
+            flash.message = "TaskBudgetStatus ${taskBudgetStatusInstance.id} created"
+            redirect(action:show,id:taskBudgetStatusInstance.id)
+        }
+        else {
+            render(view:'create',model:[taskBudgetStatusInstance:taskBudgetStatusInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/TaskDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskDetailedController.groovy	(revision 753)
@@ -0,0 +1,918 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+import com.zeddware.grails.plugins.filterpane.FilterUtils
+import org.springframework.web.servlet.support.RequestContextUtils as RCU
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager'])
+class TaskDetailedController extends BaseController {
+
+    def authService
+    def taskService
+    def taskSearchService
+    def taskReportService
+    def filterService
+    def exportService
+    def dateUtilService
+
+    // these actions only accept POST requests
+    static allowedMethods = [save:'POST',update:'POST',restore:'POST', trash:'POST',
+                                                approve:'POST', renegeApproval:'POST', complete:'POST',
+                                                reopen:'POST', setAttentionFlag:'POST', clearAttentionFlag:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def index = { redirect(action: 'search', params: params) }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def setSearchParamsMax = {
+        def max = 1000
+        if(params.newMax?.isInteger()) {
+            def i = params.newMax.toInteger()
+            if(i > 0 && i <= max)
+                session.taskSearchParamsMax = params.newMax
+            if(i > max)
+                session.taskSearchParamsMax = max
+        }
+        forward(action: 'search', params: params)
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def setSearchCalendarParamsMax = {
+        def max = 1000
+        if(params.newMax?.isInteger()) {
+            def i = params.newMax.toInteger()
+            if(i > 0 && i <= max)
+                session.taskSearchCalendarParamsMax = params.newMax
+            if(i > max)
+                session.taskSearchCalendarParamsMax = max
+        }
+        forward(action: 'searchCalendar', params: params)
+    }
+
+    /**
+    * Search for tasks.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def search = {
+
+        if(session.taskSearchParamsMax)
+            params.max = session.taskSearchParamsMax
+
+        // Protect filterPane.
+        params.max = Math.min( params.max ? params.max.toInteger() : 100,  1000 )
+
+        // View main data.
+        def taskInstanceList = []
+        def taskInstanceTotal
+        def filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
+        def isFilterApplied = FilterUtils.isFilterApplied(params)
+
+        // Restore search unless a new search is being requested.
+        if(!params.quickSearch && !filterParams) {
+            if(session.taskSearchFilterParams) {
+                session.taskSearchFilterParams.each() { params[it.key] = it.value }
+                params.filter = session.taskSearchFilter
+                isFilterApplied = FilterUtils.isFilterApplied(params)
+            }
+        }
+        if(!params.quickSearch) {
+            if(session.taskSearchQuickSearch) {
+                params.quickSearch = session.taskSearchQuickSearch
+                params.person = Person.get(session.taskQuickSearchPersonId.toLong())
+                params.startDate = session.taskQuickSearchStartDate
+                params.endDate = session.taskQuickSearchEndDate
+                params.includeCompleted = session.taskQuickSearchIncludeCompleted
+            }
+        }
+
+        // Remember sort if supplied, otherwise try to restore.
+        if(params.sort && params.order) {
+            // Reset to defaultSort if requested.
+            if(params.sort == 'defaultSort') {
+                params.sort = null
+                params.order = null
+                session.removeAttribute("taskSearchSort")
+                session.removeAttribute("taskSearchOrder")
+            }
+            else {
+                session.taskSearchSort = params.sort
+                session.taskSearchOrder = params.order
+            }
+        }
+        else if(session.taskSearchSort && session.taskSearchOrder) {
+            params.sort = session.taskSearchSort
+            params.order = session.taskSearchOrder
+        }
+
+        if(isFilterApplied) {
+            // filterPane:
+            params.sort = params.sort ?: "id"
+            params.order = params.order ?: "desc"
+            if(params.sort == "attentionFlag") // See ticket #64 in Trac.
+                params.sort = "id"
+            // Prevent tasks in the trash being returned unless explicitly requested.
+            if(!params.filter.op.trash) {
+                params.filter.op.trash = "Equal"
+                params.filter.trash = "false"
+            }
+            // Call filterService.
+            taskInstanceList = filterService.filter( params, Task )
+            taskInstanceTotal = filterService.count( params, Task )
+            filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
+            // Remember search.
+            session.taskSearchFilterParams = new LinkedHashMap(filterParams)
+            session.taskSearchFilter = new LinkedHashMap(params.filter)
+        }
+        else {
+            // Quick Search:
+            def result = taskSearchService.getQuickSearch(params, RCU.getLocale(request))
+            taskInstanceList = result.taskInstanceList
+            taskInstanceTotal = result.taskInstanceList.totalCount
+            params.message = result.message
+            params.quickSearch = result.quickSearch
+            params.person = result.person
+            params.startDate = result.startDate
+            params.endDate = result.endDate
+            params.includeCompleted = result.includeCompleted
+            // Remember search.
+            session.removeAttribute("taskSearchFilterParams")
+            session.removeAttribute("taskSearchFilter")
+            session.taskSearchQuickSearch = result.quickSearch
+            session.taskQuickSearchPersonId = result.person.id
+            session.taskQuickSearchStartDate = result.startDate
+            session.taskQuickSearchEndDate = result.endDate
+            session.taskQuickSearchIncludeCompleted = result.includeCompleted
+        }
+
+        // export plugin:
+        if(params?.format && params.format != "html") {
+
+            def dateFmt = { date ->
+                formatDate(format: "EEE, dd-MMM-yyyy", date: date)
+            }
+
+            String title
+            if(params.quickSearch)
+                title = params.message
+            else
+                title = "Filtered tasks."
+
+            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
+            response.setHeader("Content-disposition", "attachment; filename=Tasks.${params.extension}")
+            List fields = ["id", "targetStartDate", "description", "leadPerson", "taskPriority", "taskType", "taskStatus"]
+            Map labels = ["id": "ID", "targetStartDate": "Target Start Date", "description": "Description",
+                                    "leadPerson": "Lead Person", "taskPriority": "Task Priority",
+                                    "taskType": "Task Type", "taskStatus": "Task Status"]
+            Map formatters = [ targetStartDate: dateFmt]
+            Map parameters = [title: title, separator: ","]
+
+            exportService.export(params.format, response.outputStream, taskInstanceList, fields, labels, formatters, parameters)
+        }
+
+        // Add some basic params to filterParams.
+        filterParams.max = params.max
+        filterParams.offset = params.offset?.toInteger() ?: 0
+        filterParams.sort = params.sort ?: "id"
+        filterParams.order = params.order ?: "desc"
+
+        // Get some associatedProperty values for filterpane.
+        def associatedPropertyValues = [:]
+        def associatedPropertyMax = 10000
+        associatedPropertyValues.taskPriorityList = TaskPriority.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        def lastNameQuery = 'select distinct p.lastName from Person p where p.isActive = ? order by p.lastName'
+        associatedPropertyValues.lastNameList = Person.executeQuery(lastNameQuery, [true], [max:associatedPropertyMax])
+        def firstNameQuery = 'select distinct p.firstName from Person p where p.isActive = ? order by p.firstName'
+        associatedPropertyValues.firstNameList = Person.executeQuery(firstNameQuery, [true], [max:associatedPropertyMax])
+        associatedPropertyValues.taskGroupList = TaskGroup.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        associatedPropertyValues.assetList = Asset.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        associatedPropertyValues.taskStatusList = TaskStatus.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        associatedPropertyValues.taskTypeList = TaskType.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        def startOfYearRange = dateUtilService.getYearFromDate(dateUtilService.plusYear(new Date(), -10))
+        def endOfYearRange = dateUtilService.getYearFromDate(dateUtilService.plusYear(new Date(), 10))
+        associatedPropertyValues.yearRange = startOfYearRange..endOfYearRange
+
+        return[ taskInstanceList: taskInstanceList,
+                        taskInstanceTotal: taskInstanceTotal,
+                        filterParams: filterParams,
+                        params: params,
+                        associatedPropertyValues: associatedPropertyValues,
+                        quickSearchSelection: taskSearchService.quickSearchSelection]
+
+    } // search
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def searchCalendar = {
+
+        // No pagination for calendar.
+        params.offset = 0
+
+        // Restore params.max
+        if(session.taskSearchCalendarParamsMax)
+            params.max = session.taskSearchCalendarParamsMax
+
+        // Protect filterPane.
+        params.max = Math.min( params.max ? params.max.toInteger() : 100,  1000 )
+
+        def displayList = []
+        def taskInstanceList = []
+        def taskInstanceTotal
+        def filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
+        def isFilterApplied = FilterUtils.isFilterApplied(params)
+
+        // Restore search unless a new search is being requested.
+        if(!params.quickSearch && !filterParams) {
+            if(session.taskSearchCalendarFilterParams) {
+                session.taskSearchCalendarFilterParams.each() { params[it.key] = it.value }
+                params.filter = session.taskSearchCalendarFilter
+                isFilterApplied = FilterUtils.isFilterApplied(params)
+            }
+        }
+        if(!params.quickSearch) {
+            if(session.taskSearchCalendarQuickSearch) {
+                params.quickSearch = session.taskSearchCalendarQuickSearch
+                params.person = Person.get(session.taskCalendarQuickSearchPersonId.toLong())
+                params.startDate = session.taskCalendarQuickSearchStartDate
+                params.endDate = session.taskCalendarQuickSearchEndDate
+                params.includeCompleted = session.taskCalendarQuickSearchIncludeCompleted
+            }
+        }
+
+        // The date the calendar will use to determine the month to show.
+        // Use session, if not specified in params, otherwise use today.
+        def showDate = new Date()
+        if(params.showMonth) {
+            if(params.showYear)
+                showDate = dateUtilService.makeDate(params.showYear, params.showMonth)
+            else
+                showDate = dateUtilService.makeDate(dateUtilService.getYearFromDate(showDate), params.showMonth)
+            // Remember the showDate.
+            session.taskSearchCalendarShowDate = showDate
+        }
+        else if(session.taskSearchCalendarShowDate)
+            showDate = session.taskSearchCalendarShowDate
+
+        // Get the dates for the calendar month controls.
+        def calendarMonthControls = getCalendarMonthControls(showDate)
+
+        if(isFilterApplied) {
+            // filterPane:
+            params.sort = params.sort ?: "id"
+            params.order = params.order ?: "desc"
+            if(params.sort == "attentionFlag") // See ticket #64 in Trac.
+                params.sort = "id"
+            // Prevent tasks in the trash being returned unless explicitly requested.
+            if(!params.filter.op.trash) {
+                params.filter.op.trash = "Equal"
+                params.filter.trash = "false"
+            }
+            // Call filterService.
+            taskInstanceList = filterService.filter( params, Task )
+            taskInstanceTotal = filterService.count( params, Task )
+            filterParams = com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params)
+            // Remember search.
+            session.taskSearchCalendarFilterParams = new LinkedHashMap(filterParams)
+            session.taskSearchCalendarFilter = new LinkedHashMap(params.filter)
+        }
+        else {
+            // Quick Search:
+            def result = taskSearchService.getQuickSearch(params, RCU.getLocale(request))
+            taskInstanceList = result.taskInstanceList
+            taskInstanceTotal = result.taskInstanceList.totalCount
+            params.message = result.message
+            params.quickSearch = result.quickSearch
+            params.person = result.person
+            params.startDate = result.startDate
+            params.endDate = result.endDate
+            params.includeCompleted = result.includeCompleted
+            // Remember search.
+            session.removeAttribute("taskSearchCalendarFilterParams")
+            session.removeAttribute("taskSearchCalendarFilter")
+            session.taskSearchCalendarQuickSearch = result.quickSearch
+            session.taskCalendarQuickSearchPersonId = result.person.id
+            session.taskCalendarQuickSearchStartDate = result.startDate
+            session.taskCalendarQuickSearchEndDate = result.endDate
+            session.taskCalendarQuickSearchIncludeCompleted = result.includeCompleted
+        }
+
+//         displayList = taskReportService.getWorkLoadSummary(
+//                                     [taskInstanceList: taskInstanceList], RCU.getLocale(request)
+//                                 ).displayList
+
+        // export plugin:
+        if(params?.format && params.format != "html") {
+
+            def dateFmt = { date ->
+                formatDate(format: "EEE, dd-MMM-yyyy", date: date)
+            }
+
+            String title
+            if(params.quickSearch)
+                title = params.message
+            else
+                title = "Filtered tasks."
+
+            response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
+            response.setHeader("Content-disposition", "attachment; filename=Tasks.${params.extension}")
+            List fields = ["id", "targetStartDate", "description", "leadPerson", "taskPriority", "taskType", "taskStatus"]
+            Map labels = ["id": "ID", "targetStartDate": "Target Start Date", "description": "Description",
+                                    "leadPerson": "Lead Person", "taskPriority": "Task Priority",
+                                    "taskType": "Task Type", "taskStatus": "Task Status"]
+            Map formatters = [ targetStartDate: dateFmt]
+            Map parameters = [title: title, separator: ","]
+
+            exportService.export(params.format, response.outputStream, taskInstanceList, fields, labels, formatters, parameters)
+        }
+
+        if(taskInstanceTotal > params.max)
+            params.errorMessage = g.message(code:"task.search.calendar.text.too.many.results", args:[params.max])
+
+        // Add some basic params to filterParams.
+        filterParams.max = params.max
+        filterParams.offset = params.offset?.toInteger() ?: 0
+        filterParams.sort = params.sort ?: "id"
+        filterParams.order = params.order ?: "desc"
+
+        // Get some associatedProperty values for filterpane.
+        def associatedPropertyValues = [:]
+        def associatedPropertyMax = 10000
+        associatedPropertyValues.taskPriorityList = TaskPriority.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        def lastNameQuery = 'select distinct p.lastName from Person p where p.isActive = ? order by p.lastName'
+        associatedPropertyValues.lastNameList = Person.executeQuery(lastNameQuery, [true], [max:associatedPropertyMax])
+        def firstNameQuery = 'select distinct p.firstName from Person p where p.isActive = ? order by p.firstName'
+        associatedPropertyValues.firstNameList = Person.executeQuery(firstNameQuery, [true], [max:associatedPropertyMax])
+        associatedPropertyValues.taskGroupList = TaskGroup.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        associatedPropertyValues.assetList = Asset.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        associatedPropertyValues.taskStatusList = TaskStatus.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        associatedPropertyValues.taskTypeList = TaskType.findAllByIsActive(true, [max:associatedPropertyMax, sort:'name'])
+        def startOfYearRange = dateUtilService.getYearFromDate(dateUtilService.plusYear(new Date(), -10))
+        def endOfYearRange = dateUtilService.getYearFromDate(dateUtilService.plusYear(new Date(), 10))
+        associatedPropertyValues.yearRange = startOfYearRange..endOfYearRange
+
+        return[taskInstanceList: taskInstanceList,
+                        taskInstanceTotal: taskInstanceTotal,
+                        filterParams: filterParams,
+                        params: params,
+                        associatedPropertyValues: associatedPropertyValues,
+                        showDate: showDate,
+                        today: calendarMonthControls.today,
+                        previousMonth: calendarMonthControls.previousMonth,
+                        nextMonth: calendarMonthControls.nextMonth,
+                        previousYear: calendarMonthControls.previousYear,
+                        nextYear: calendarMonthControls.nextYear,
+                        quickSearchSelection: taskSearchService.quickSearchSelection]
+
+    } // searchCalendar
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        // Used by navigation.
+        if(params.id == 'nav') {
+            params.id = session.currentTaskId ?: null
+            redirect(action: show, id: params.id)
+            return
+        }
+
+        def showTab = [:]
+        switch (params.showTab) {
+            case "showProcedureTab":
+                showTab.procedure =  new String("true")
+                break
+            case "showRecurrenceTab":
+                showTab.recurrence =  new String("true")
+                break
+            case "showInventoryTab":
+                showTab.inventory = new String("true")
+                break
+            case "showSubTasksTab":
+                showTab.subTasks = new String("true")
+                break
+            default:
+                showTab.task = new String("true")
+        }
+
+        def taskInstance = Task.get( params.id )
+
+        if(!taskInstance) {
+            flash.message = "Task not found with id ${params.id}"
+            redirect(action: 'search')
+        }
+        else {
+            // Remember the current task id for use with navigation.
+            session.currentTaskId = params.id
+
+            params.max = 10
+            params.order = "desc"
+            params.sort = "id"
+
+            def entryFaultList = Entry.withCriteria {
+                                                                eq("entryType", EntryType.get(1))
+                                                                eq("task", taskInstance)
+                                                        }
+
+            def entryCauseList = Entry.withCriteria {
+                                                                eq("entryType", EntryType.get(2))
+                                                                eq("task", taskInstance)
+                                                        }
+
+            def entryWorkDoneList = Entry.withCriteria {
+                                                                eq("entryType", EntryType.get(3))
+                                                                eq("task", taskInstance)
+                                                        }
+
+            def subTaskInstanceList = Task.findAllByParentTaskAndTrash(taskInstance, false, params)
+            def subTaskInstanceTotal = Task.countByParentTaskAndTrash(taskInstance, false)
+
+            def inventoryMovementList = InventoryMovement.findAllByTask(taskInstance, [max:100, sort:"id", order:"desc", offset:0])
+
+            def taskModificationList = TaskModification.findAllByTask(taskInstance, [max:100, sort:"id", order:"asc", offset:0])
+
+            def assignedGroupList = taskInstance.assignedGroups.sort { p1, p2 -> p1.personGroup.name.compareToIgnoreCase(p2.personGroup.name) }
+            def assignedPersonList = taskInstance.assignedPersons.sort { p1, p2 -> p1.person.firstName.compareToIgnoreCase(p2.person.firstName) }
+
+            def taskProcedureInstance = TaskProcedure.get(taskInstance.taskProcedure?.id)
+            def taskProcedureExits = new Boolean("true")
+            if(!taskProcedureInstance) {
+                taskProcedureExits = false
+            }
+
+            def maParams = [:]
+            maParams.max = 100
+            maParams.order = "asc"
+            maParams.sort = "procedureStepNumber"
+            def maintenanceActionList = MaintenanceAction.findAllByTaskProcedure(taskProcedureInstance, maParams)
+
+            def taskRecurringScheduleInstance = TaskRecurringSchedule.get(taskInstance.taskRecurringSchedule?.id)
+            def taskRecurringScheduleExits= new Boolean("true")
+            if(!taskRecurringScheduleInstance) {
+                taskRecurringScheduleExits = false
+            }
+
+            return [ taskInstance: taskInstance,
+                            entryFaultList: entryFaultList,
+                            entryCauseList: entryCauseList,
+                            entryWorkDoneList: entryWorkDoneList,
+                            taskProcedureInstance: taskProcedureInstance,
+                            taskProcedureExits: taskProcedureExits,
+                            showTab: showTab,
+                            subTaskInstanceList: subTaskInstanceList,
+                            subTaskInstanceTotal: subTaskInstanceTotal,
+                            subTaskInstanceMax: params.max,
+                            maintenanceActionList: maintenanceActionList,
+                            taskRecurringScheduleInstance: taskRecurringScheduleInstance,
+                            taskRecurringScheduleExits: taskRecurringScheduleExits,
+                            inventoryMovementList: inventoryMovementList,
+                            taskModificationList: taskModificationList,
+                            assignedGroupList: assignedGroupList,
+                            assignedPersonList: assignedPersonList]
+        }
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def restore = {
+
+        def result = taskService.restore(params)
+
+        if(!result.error) {
+                flash.message = "Task ${params.id} has been restored."
+                redirect(action: show, id: params.id)
+                return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.taskInstance)
+            redirect(action: show, id: params.id)
+        else
+            redirect(action: 'search')
+
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def trash = {
+
+        def result = taskService.trash(params)
+
+        if(!result.error) {
+                flash.message = "Task ${params.id} has been moved to trash."
+                redirect(action: 'search')
+                return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.taskInstance)
+            redirect(action: show, id: params.id)
+        else
+            redirect(action: 'search')
+
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager'])
+    def approve = {
+
+        def result = taskService.approve(params)
+
+        if(!result.error) {
+                flash.message = "Task ${params.id} has been approved."
+                redirect(action: show, id: params.id)
+                return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.taskInstance)
+            redirect(action: show, id: params.id)
+        else
+            redirect(action: 'search')
+
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager'])
+    def renegeApproval = {
+
+        def result = taskService.renegeApproval(params)
+
+        if(!result.error) {
+                flash.message = "Task ${params.id} has had approval removed."
+                redirect(action: show, id: params.id)
+                return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.taskInstance)
+            redirect(action: show, id: params.id)
+        else
+            redirect(action: 'search')
+
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def complete = {
+
+        def result = taskService.complete(params)
+
+        if(!result.error) {
+                flash.message = "Task ${params.id} has been completed."
+                redirect(action: show, id: params.id)
+                return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.taskInstance)
+            redirect(action: show, id: params.id)
+        else
+            redirect(action: 'search')
+
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def setAttentionFlag = {
+
+        def result = taskService.setAttentionFlag(params)
+
+        if(!result.error) {
+                flash.message = "Task ${params.id} has been flagged for attention."
+                redirect(action: show, id: params.id)
+                return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.taskInstance)
+            redirect(action: show, id: params.id)
+        else
+            redirect(action: 'search')
+
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def clearAttentionFlag = {
+
+        def result = taskService.clearAttentionFlag(params)
+
+        if(!result.error) {
+                flash.message = "Task ${params.id} attention flag cleared."
+                redirect(action: show, id: params.id)
+                return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.taskInstance)
+            redirect(action: show, id: params.id)
+        else
+            redirect(action: 'search')
+
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def reopen = {
+
+        def result = taskService.reopen(params)
+
+        if(!result.error) {
+                flash.message = "Task ${params.id} has been reopened."
+                redirect(action: show, id: params.id)
+                return
+        }
+
+        flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        if(result.taskInstance)
+            redirect(action: show, id: params.id)
+        else
+            redirect(action: 'search')
+
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        // Used by navigation.
+        if(params.id == 'nav') {
+            params.id = session.currentTaskId ?: null
+            redirect(action: edit, id: params.id)
+            return
+        }
+
+        def taskInstance = Task.get( params.id )
+
+        if(!taskInstance) {
+            flash.message = "Task not found with id ${params.id}"
+            redirect(action: 'search')
+        }
+        else {
+            // Remember the current task id for use with navigation.
+            session.currentTaskId = params.id
+
+            if(taskInstance.trash) {
+                flash.message = "You may not edit tasks that are in the trash."
+                redirect(action: 'show', id: taskInstance.id)
+                return
+            }
+//             def possibleParentList = taskService.possibleParentList(taskInstance)
+//             return [ taskInstance : taskInstance, possibleParentList: possibleParentList ]
+            return [ taskInstance : taskInstance ]
+        }
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def update = {
+
+        def result = taskService.update(params)
+
+        if(!result.error) {
+                flash.message = "Task ${params.id} updated"
+                redirect(action: show, id: params.id)
+                return
+        }
+
+        if(result.error.code == "task.modifications.failedToSave")
+            flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        render(view:'edit',model:[taskInstance:result.taskInstance.attach()])
+
+    }
+
+    /**
+    * The create action is used to create scheduled types of tasks.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager'])
+    def create = {
+        def taskInstance = new Task()
+
+        // Set the targetStartDate if specified, used by searchCalendar view.
+        if(params.year && params.month && params.day) {
+            def date = dateUtilService.makeDate(params.year, params.month, params.day)
+            taskInstance.targetStartDate = date
+            taskInstance.targetCompletionDate = date
+        }
+
+        // Default leadPerson to current user, unless supplied in params.
+        taskInstance.leadPerson = authService.currentUser
+
+        // Apply params, overiding anything above.
+        taskInstance.properties = params
+
+        def scheduledTaskTypes = taskService.scheduledTaskTypes
+        def scheduledTaskPriorities = taskService.scheduledTaskPriorities
+        taskInstance.taskPriority = scheduledTaskPriorities.default
+        return ['taskInstance': taskInstance,
+                    'scheduledTaskTypes': scheduledTaskTypes,
+                    'scheduledTaskPriorities': scheduledTaskPriorities.list]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def save = {
+        def result = taskService.save(params)
+
+        if(!result.error) {
+            flash.message = "Task ${result.taskInstance.id} created."
+            redirect(action: 'show', id: result.taskInstance.id)
+            return
+        }
+
+        if(result.error.code == "task.modifications.failedToSave")
+            flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+
+        def scheduledTaskTypes = taskService.scheduledTaskTypes
+        def scheduledTaskPriorities = taskService.scheduledTaskPriorities
+        render(view:'create', model:[taskInstance:result.taskInstance,
+                                                    'scheduledTaskTypes': scheduledTaskTypes,
+                                                    'scheduledTaskPriorities': scheduledTaskPriorities.list])
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def listSubTasks = {
+        def parentTaskInstance = Task.get(params.id)
+
+        if(!parentTaskInstance) {
+            flash.message = "Task not found with id ${params.id}"
+            redirect(action: 'search')
+        }
+        else {
+        params.max = Math.min( params.max ? params.max.toInteger() : 200,  200)
+        def subTaskInstanceList = Task.findAllByParentTaskAndTrash(parentTaskInstance, false, params)
+        def subTaskInstanceTotal = Task.countByParentTaskAndTrash(parentTaskInstance, false)
+
+        [ taskInstanceList: subTaskInstanceList,
+            taskInstanceTotal:  subTaskInstanceTotal,
+            parentTaskInstance: parentTaskInstance]
+        }
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def createSubTask = {
+        def parentTaskInstance = Task.get(params.id)
+
+        if(parentTaskInstance) {
+
+            def result = taskService.createSubTask(parentTaskInstance)
+            if(!result.error) {
+                flash.message = "Sub Task ${result.taskInstance.id} created, please edit and update to your requirements."
+                redirect(action: 'edit', id: result.taskInstance.id)
+            }
+            else {
+                if(result.taskInstance.errors.hasFieldErrors("parentTask")) {
+                    flash.errorMessage = g.message(code:"task.operationNotPermittedOnTaskInTrash")
+                    redirect(action: 'show', id:  parentTaskInstance.id)
+                }
+                else {
+                    render(view: 'create', model:[taskInstance: result.taskInstance])
+                }
+            }
+        }
+
+        else {
+            flash.message = "Task not found with id ${params.id}"
+            redirect(action: 'search')
+        }
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def createUnscheduled = {
+        def taskInstance = new Task()
+
+        // Default leadPerson to current user, unless supplied in params.
+        taskInstance.leadPerson = authService.currentUser
+        taskInstance.properties = params
+
+        // Always for Unscheduled task.
+        taskInstance.taskType = TaskType.get(2) // Unscheduled Breakin.
+        def unscheduledTaskPriorities = taskService.unscheduledTaskPriorities
+        taskInstance.taskPriority = unscheduledTaskPriorities.default
+
+        return ['taskInstance': taskInstance, 'unscheduledTaskPriorities': unscheduledTaskPriorities.list]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def saveUnscheduled = {
+        def result = taskService.saveUnscheduled(params)
+
+        if(!result.error) {
+            flash.message = "Task ${result.taskInstance.id} created."
+            redirect(action: 'show', id: result.taskInstance.id)
+            return
+        }
+
+        if(result.error.code == "task.modifications.failedToSave")
+            flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        def unscheduledTaskPriorities = taskService.unscheduledTaskPriorities
+
+        render(view:'createUnscheduled',
+                    model: ['taskInstance': result.taskInstance, 'unscheduledTaskPriorities': unscheduledTaskPriorities.list])
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def createImmediateCallout = {
+        def taskInstance = new Task()
+
+        def entryFaultInstance = new Entry(entryType: EntryType.get(1))  // Fault.
+        def entryCauseInstance = new Entry(entryType: EntryType.get(2))  // Cause.
+        def entryWorkDoneInstance = new Entry(entryType: EntryType.get(3))  // Work Done.
+
+        return ['taskInstance': taskInstance,
+                        'entryFaultInstance': entryFaultInstance,
+                        'entryCauseInstance': entryCauseInstance,
+                        'entryWorkDoneInstance': entryWorkDoneInstance]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def saveImmediateCallout = {
+        def result = taskService.saveImmediateCallout(params)
+
+        if(!result.error) {
+            flash.message = "Task ${result.taskInstance.id} created."
+            redirect(action: 'show', id: result.taskInstance.id)
+            return
+        }
+
+        if(result.error.code == "task.modifications.failedToSave")
+            flash.errorMessage = g.message(code: result.error.code, args: result.error.args)
+
+        render(view:'createImmediateCallout',
+                    model: ['taskInstance': result.taskInstance,
+                                'entryFaultInstance': result.entryFaultInstance,
+                                'entryCauseInstance': result.entryCauseInstance,
+                                'entryWorkDoneInstance': result.entryWorkDoneInstance])
+
+    }
+
+    /**
+    * Render a users total work done hours.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def workDone = {
+        def result = taskSearchService.getWorkDone(params, RCU.getLocale(request))
+
+        params.message = result.message
+
+        return[entries: result.entries,
+                    totalEntries : result.totalEntries,
+                    startOfDay: result.startOfDay,
+                    person: result.person,
+                    totalHours: result.totalHours,
+                    totalMinutes: result.totalMinutes]
+    } // workDone
+
+    /**
+    * Render work load hours.
+    */
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def workLoad= {
+        def result = taskSearchService.getWorkLoad(params, RCU.getLocale(request))
+
+        params.message = result.message
+        params.errorMessage = result.errorMessage
+
+        return[tasks: result.tasks,
+                    startDate: result.startDate,
+                    endDate: result.endDate,
+                    taskGroups: result.taskGroups,
+                    taskStatusList: result.taskStatusList,
+                    workLoadGroups: result.workLoadGroups,
+                    totalHours: result.totalHours,
+                    totalMinutes: result.totalMinutes]
+    } // workLoad
+
+    /**
+    * Get some integers for use by the month control links.
+    */
+    private getCalendarMonthControls(Date showDate) {
+        def result = [:]
+        result.today = [:]
+        result.today.date = new Date()
+        result.today.month = dateUtilService.getMonthFromDate(result.today.date)
+        result.today.year = dateUtilService.getYearFromDate(result.today.date)
+        result.nextMonth = [:]
+        result.nextMonth.date = dateUtilService.plusMonth(showDate)
+        result.nextMonth.month = dateUtilService.getMonthFromDate(result.nextMonth.date)
+        result.nextMonth.year = dateUtilService.getYearFromDate(result.nextMonth.date)
+        result.previousMonth =  [:]
+        result.previousMonth.date = dateUtilService.plusMonth(showDate, -1)
+        result.previousMonth.month = dateUtilService.getMonthFromDate(result.previousMonth.date)
+        result.previousMonth.year = dateUtilService.getYearFromDate(result.previousMonth.date)
+        result.nextYear = [:]
+        result.nextYear.date = dateUtilService.plusYear(showDate)
+        result.nextYear.month = dateUtilService.getMonthFromDate(result.nextYear.date)
+        result.nextYear.year = dateUtilService.getYearFromDate(result.nextYear.date)
+        result.previousYear = [:]
+        result.previousYear.date = dateUtilService.plusYear(showDate, -1)
+        result.previousYear.month = dateUtilService.getMonthFromDate(result.previousYear.date)
+        result.previousYear.year = dateUtilService.getYearFromDate(result.previousYear.date)
+        return result
+    }
+
+} // end of class.
Index: branches/features/taskProcedureRework/grails-app/controllers/TaskGroupDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskGroupDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskGroupDetailedController.groovy	(revision 753)
@@ -0,0 +1,110 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager'])
+class TaskGroupDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ taskGroupInstanceList: TaskGroup.list( params ), taskGroupInstanceTotal: TaskGroup.count() ]
+    }
+
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def taskGroupInstance = TaskGroup.get( params.id )
+
+        if(!taskGroupInstance) {
+            flash.message = "TaskGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ taskGroupInstance : taskGroupInstance ] }
+    }
+
+    def delete = {
+        def taskGroupInstance = TaskGroup.get( params.id )
+        if(taskGroupInstance) {
+            try {
+                taskGroupInstance.delete(flush:true)
+                flash.message = "TaskGroup ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "TaskGroup ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "TaskGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def taskGroupInstance = TaskGroup.get( params.id )
+
+        if(!taskGroupInstance) {
+            flash.message = "TaskGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ taskGroupInstance : taskGroupInstance ]
+        }
+    }
+
+    def update = {
+        def taskGroupInstance = TaskGroup.get( params.id )
+        if(taskGroupInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(taskGroupInstance.version > version) {
+                    
+                    taskGroupInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[taskGroupInstance:taskGroupInstance])
+                    return
+                }
+            }
+            taskGroupInstance.properties = params
+            if(!taskGroupInstance.hasErrors() && taskGroupInstance.save(flush: true)) {
+                flash.message = "TaskGroup ${params.id} updated"
+                redirect(action:show,id:taskGroupInstance.id)
+            }
+            else {
+                render(view:'edit',model:[taskGroupInstance:taskGroupInstance])
+            }
+        }
+        else {
+            flash.message = "TaskGroup not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def taskGroupInstance = new TaskGroup()
+        taskGroupInstance.properties = params
+        return ['taskGroupInstance':taskGroupInstance]
+    }
+
+    def save = {
+        def taskGroupInstance = new TaskGroup(params)
+        if(!taskGroupInstance.hasErrors() && taskGroupInstance.save(flush: true)) {
+            flash.message = "TaskGroup ${taskGroupInstance.id} created"
+            redirect(action:show,id:taskGroupInstance.id)
+        }
+        else {
+            render(view:'create',model:[taskGroupInstance:taskGroupInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/TaskModificationTypeController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskModificationTypeController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskModificationTypeController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class TaskModificationTypeController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ taskModificationTypeInstanceList: TaskModificationType.list( params ), taskModificationTypeInstanceTotal: TaskModificationType.count() ]
+    }
+
+    def show = {
+        def taskModificationTypeInstance = TaskModificationType.get( params.id )
+
+        if(!taskModificationTypeInstance) {
+            flash.message = "TaskModificationType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ taskModificationTypeInstance : taskModificationTypeInstance ] }
+    }
+
+    def delete = {
+        def taskModificationTypeInstance = TaskModificationType.get( params.id )
+        if(taskModificationTypeInstance) {
+            try {
+                taskModificationTypeInstance.delete(flush:true)
+                flash.message = "TaskModificationType ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "TaskModificationType ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "TaskModificationType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def taskModificationTypeInstance = TaskModificationType.get( params.id )
+
+        if(!taskModificationTypeInstance) {
+            flash.message = "TaskModificationType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ taskModificationTypeInstance : taskModificationTypeInstance ]
+        }
+    }
+
+    def update = {
+        def taskModificationTypeInstance = TaskModificationType.get( params.id )
+        if(taskModificationTypeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(taskModificationTypeInstance.version > version) {
+                    
+                    taskModificationTypeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[taskModificationTypeInstance:taskModificationTypeInstance])
+                    return
+                }
+            }
+            taskModificationTypeInstance.properties = params
+            if(!taskModificationTypeInstance.hasErrors() && taskModificationTypeInstance.save(flush: true)) {
+                flash.message = "TaskModificationType ${params.id} updated"
+                redirect(action:show,id:taskModificationTypeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[taskModificationTypeInstance:taskModificationTypeInstance])
+            }
+        }
+        else {
+            flash.message = "TaskModificationType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def taskModificationTypeInstance = new TaskModificationType()
+        taskModificationTypeInstance.properties = params
+        return ['taskModificationTypeInstance':taskModificationTypeInstance]
+    }
+
+    def save = {
+        def taskModificationTypeInstance = new TaskModificationType(params)
+        if(!taskModificationTypeInstance.hasErrors() && taskModificationTypeInstance.save(flush: true)) {
+            flash.message = "TaskModificationType ${taskModificationTypeInstance.id} created"
+            redirect(action:show,id:taskModificationTypeInstance.id)
+        }
+        else {
+            render(view:'create',model:[taskModificationTypeInstance:taskModificationTypeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/TaskPriorityController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskPriorityController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskPriorityController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class TaskPriorityController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ taskPriorityInstanceList: TaskPriority.list( params ), taskPriorityInstanceTotal: TaskPriority.count() ]
+    }
+
+    def show = {
+        def taskPriorityInstance = TaskPriority.get( params.id )
+
+        if(!taskPriorityInstance) {
+            flash.message = "TaskPriority not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ taskPriorityInstance : taskPriorityInstance ] }
+    }
+
+    def delete = {
+        def taskPriorityInstance = TaskPriority.get( params.id )
+        if(taskPriorityInstance) {
+            try {
+                taskPriorityInstance.delete(flush:true)
+                flash.message = "TaskPriority ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "TaskPriority ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "TaskPriority not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def taskPriorityInstance = TaskPriority.get( params.id )
+
+        if(!taskPriorityInstance) {
+            flash.message = "TaskPriority not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ taskPriorityInstance : taskPriorityInstance ]
+        }
+    }
+
+    def update = {
+        def taskPriorityInstance = TaskPriority.get( params.id )
+        if(taskPriorityInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(taskPriorityInstance.version > version) {
+                    
+                    taskPriorityInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[taskPriorityInstance:taskPriorityInstance])
+                    return
+                }
+            }
+            taskPriorityInstance.properties = params
+            if(!taskPriorityInstance.hasErrors() && taskPriorityInstance.save(flush: true)) {
+                flash.message = "TaskPriority ${params.id} updated"
+                redirect(action:show,id:taskPriorityInstance.id)
+            }
+            else {
+                render(view:'edit',model:[taskPriorityInstance:taskPriorityInstance])
+            }
+        }
+        else {
+            flash.message = "TaskPriority not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def taskPriorityInstance = new TaskPriority()
+        taskPriorityInstance.properties = params
+        return ['taskPriorityInstance':taskPriorityInstance]
+    }
+
+    def save = {
+        def taskPriorityInstance = new TaskPriority(params)
+        if(!taskPriorityInstance.hasErrors() && taskPriorityInstance.save(flush: true)) {
+            flash.message = "TaskPriority ${taskPriorityInstance.id} created"
+            redirect(action:show,id:taskPriorityInstance.id)
+        }
+        else {
+            render(view:'create',model:[taskPriorityInstance:taskPriorityInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/TaskProcedureController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskProcedureController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskProcedureController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class TaskProcedureController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ taskProcedureInstanceList: TaskProcedure.list( params ), taskProcedureInstanceTotal: TaskProcedure.count() ]
+    }
+
+    def show = {
+        def taskProcedureInstance = TaskProcedure.get( params.id )
+
+        if(!taskProcedureInstance) {
+            flash.message = "TaskProcedure not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ taskProcedureInstance : taskProcedureInstance ] }
+    }
+
+    def delete = {
+        def taskProcedureInstance = TaskProcedure.get( params.id )
+        if(taskProcedureInstance) {
+            try {
+                taskProcedureInstance.delete(flush:true)
+                flash.message = "TaskProcedure ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "TaskProcedure ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "TaskProcedure not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def taskProcedureInstance = TaskProcedure.get( params.id )
+
+        if(!taskProcedureInstance) {
+            flash.message = "TaskProcedure not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ taskProcedureInstance : taskProcedureInstance ]
+        }
+    }
+
+    def update = {
+        def taskProcedureInstance = TaskProcedure.get( params.id )
+        if(taskProcedureInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(taskProcedureInstance.version > version) {
+                    
+                    taskProcedureInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[taskProcedureInstance:taskProcedureInstance])
+                    return
+                }
+            }
+            taskProcedureInstance.properties = params
+            if(!taskProcedureInstance.hasErrors() && taskProcedureInstance.save(flush: true)) {
+                flash.message = "TaskProcedure ${params.id} updated"
+                redirect(action:show,id:taskProcedureInstance.id)
+            }
+            else {
+                render(view:'edit',model:[taskProcedureInstance:taskProcedureInstance])
+            }
+        }
+        else {
+            flash.message = "TaskProcedure not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def taskProcedureInstance = new TaskProcedure()
+        taskProcedureInstance.properties = params
+        return ['taskProcedureInstance':taskProcedureInstance]
+    }
+
+    def save = {
+        def taskProcedureInstance = new TaskProcedure(params)
+        if(!taskProcedureInstance.hasErrors() && taskProcedureInstance.save(flush: true)) {
+            flash.message = "TaskProcedure ${taskProcedureInstance.id} created"
+            redirect(action:show,id:taskProcedureInstance.id)
+        }
+        else {
+            render(view:'create',model:[taskProcedureInstance:taskProcedureInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/TaskProcedureDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskProcedureDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskProcedureDetailedController.groovy	(revision 753)
@@ -0,0 +1,138 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager'])
+class TaskProcedureDetailedController extends BaseController {
+
+    def filterService
+
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+
+        if(!params.filter)
+        { return [taskProcedureInstanceList: TaskProcedure.list(params), taskProcedureInstanceTotal: TaskProcedure.count()] }
+
+        // filterPane:
+        return[ taskProcedureInstanceList: filterService.filter( params, TaskProcedure ),
+            taskProcedureInstanceTotal: filterService.count( params, TaskProcedure ),
+            filterParams: com.zeddware.grails.plugins.filterpane.FilterUtils.extractFilterParams(params),
+            params:params ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def search = {
+        redirect(action:list)
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def taskProcedureInstance = TaskProcedure.get( params.id )
+
+        if(!taskProcedureInstance) {
+            flash.message = "TaskProcedure not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ taskProcedureInstance : taskProcedureInstance ] }
+    }
+
+    def delete = {
+        def taskProcedureInstance = TaskProcedure.get( params.id )
+        if(taskProcedureInstance) {
+            try {
+                taskProcedureInstance.delete(flush:true)
+                flash.message = "TaskProcedure ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "TaskProcedure ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "TaskProcedure not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def taskProcedureInstance = TaskProcedure.get( params.id )
+
+        if(!taskProcedureInstance) {
+            flash.message = "TaskProcedure not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ taskProcedureInstance : taskProcedureInstance ]
+        }
+    }
+
+    def update = {
+        def taskProcedureInstance = TaskProcedure.get( params.id )
+        if(taskProcedureInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(taskProcedureInstance.version > version) {
+
+                    taskProcedureInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[taskProcedureInstance:taskProcedureInstance])
+                    return
+                }
+            }
+            taskProcedureInstance.properties = params
+            if(!taskProcedureInstance.hasErrors() && taskProcedureInstance.save(flush: true)) {
+                flash.message = "TaskProcedure ${params.id} updated"
+                redirect(action:show,id:taskProcedureInstance.id)
+            }
+            else {
+                render(view:'edit',model:[taskProcedureInstance:taskProcedureInstance])
+            }
+        }
+        else {
+            flash.message = "TaskProcedure not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        if(params.taskInstance?.id) {
+            def taskInstance = Task.get(params.taskInstance.id)
+
+            def taskProcedureInstance = new TaskProcedure()
+            taskProcedureInstance.properties = params
+            return ['taskProcedureInstance':taskProcedureInstance,
+                            taskInstance: taskInstance]
+        } else {
+            flash.message = "Please select or create a task, then go to the Procedure tab."
+            redirect(controller:"taskDetailed", action:"search")
+        }
+    }
+
+    def save = {
+        def taskProcedureInstance = new TaskProcedure(params)
+        def taskInstance = Task.get(params.taskInstance.id)
+
+        if(!taskProcedureInstance.hasErrors() && taskProcedureInstance.save(flush: true)) {
+            taskProcedureInstance.addToTasks(taskInstance)
+            flash.message = "TaskProcedure ${taskProcedureInstance.id} created."
+            redirect(action:show,id:taskProcedureInstance.id)
+        }
+        else {
+            render(view:'create',model:[taskProcedureInstance:taskProcedureInstance, taskInstance: taskInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/TaskRecurringScheduleDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskRecurringScheduleDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskRecurringScheduleDetailedController.groovy	(revision 753)
@@ -0,0 +1,103 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager'])
+class TaskRecurringScheduleDetailedController extends BaseController {
+
+    def taskRecurringScheduleService
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ taskRecurringScheduleInstanceList: TaskRecurringSchedule.list( params ), taskRecurringScheduleInstanceTotal: TaskRecurringSchedule.count() ]
+    }
+
+    @Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
+    def show = {
+        def taskRecurringScheduleInstance = TaskRecurringSchedule.get( params.id )
+
+        if(!taskRecurringScheduleInstance) {
+            flash.message = "Recurring Schedule not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ taskRecurringScheduleInstance : taskRecurringScheduleInstance ] }
+    }
+
+    def delete = {
+        def taskRecurringScheduleInstance = TaskRecurringSchedule.get( params.id )
+        if(taskRecurringScheduleInstance) {
+            try {
+                taskRecurringScheduleInstance.delete(flush: true)
+                flash.message = "Recurring Schedule ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "Recurring Schedule ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "Recurring Schedule not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def taskRecurringScheduleInstance = TaskRecurringSchedule.get( params.id )
+
+        if(!taskRecurringScheduleInstance) {
+            flash.message = "Recurring Schedule not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ taskRecurringScheduleInstance : taskRecurringScheduleInstance]
+        }
+    }
+
+    def update = {
+
+        if(!TaskRecurringSchedule.exists(params.id)) {
+            flash.message = "Recurring Schedule not found with id ${params.id}"
+            redirect(action: 'list')
+        }
+
+        def result = taskRecurringScheduleService.update(params)
+
+        if(!result.error) {
+                flash.message = "Recurring Schedule ${params.id} updated"
+                redirect(action: 'show', id: result.taskRecurringScheduleInstance.id)
+        }
+        else {
+            render(view:'edit',model:[taskRecurringScheduleInstance: result.taskRecurringScheduleInstance.attach()])
+        }
+
+    }
+
+    def create = {
+        if(!params.task?.id || !Task.exists(params.task?.id)) {
+            flash.message = "Please select a task, then create a recurring schedule for it."
+            redirect(controller:"taskDetailed", action:"search")
+            return
+        }
+        def taskRecurringScheduleInstance = new TaskRecurringSchedule(params)
+        return [taskRecurringScheduleInstance: taskRecurringScheduleInstance]
+    }
+
+    def save = {
+        def result = taskRecurringScheduleService.create(params)
+
+        if(!result.error) {
+            flash.message = "Recurring Schedule ${result.taskRecurringScheduleInstance.id} created."
+            redirect(action:show, id: result.taskRecurringScheduleInstance.id)
+        }
+        else {
+            render(view:'create',model:[taskRecurringScheduleInstance: result.taskRecurringScheduleInstance])
+        }
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/TaskStatusController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskStatusController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskStatusController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class TaskStatusController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ taskStatusInstanceList: TaskStatus.list( params ), taskStatusInstanceTotal: TaskStatus.count() ]
+    }
+
+    def show = {
+        def taskStatusInstance = TaskStatus.get( params.id )
+
+        if(!taskStatusInstance) {
+            flash.message = "TaskStatus not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ taskStatusInstance : taskStatusInstance ] }
+    }
+
+    def delete = {
+        def taskStatusInstance = TaskStatus.get( params.id )
+        if(taskStatusInstance) {
+            try {
+                taskStatusInstance.delete(flush:true)
+                flash.message = "TaskStatus ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "TaskStatus ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "TaskStatus not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def taskStatusInstance = TaskStatus.get( params.id )
+
+        if(!taskStatusInstance) {
+            flash.message = "TaskStatus not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ taskStatusInstance : taskStatusInstance ]
+        }
+    }
+
+    def update = {
+        def taskStatusInstance = TaskStatus.get( params.id )
+        if(taskStatusInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(taskStatusInstance.version > version) {
+                    
+                    taskStatusInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[taskStatusInstance:taskStatusInstance])
+                    return
+                }
+            }
+            taskStatusInstance.properties = params
+            if(!taskStatusInstance.hasErrors() && taskStatusInstance.save(flush: true)) {
+                flash.message = "TaskStatus ${params.id} updated"
+                redirect(action:show,id:taskStatusInstance.id)
+            }
+            else {
+                render(view:'edit',model:[taskStatusInstance:taskStatusInstance])
+            }
+        }
+        else {
+            flash.message = "TaskStatus not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def taskStatusInstance = new TaskStatus()
+        taskStatusInstance.properties = params
+        return ['taskStatusInstance':taskStatusInstance]
+    }
+
+    def save = {
+        def taskStatusInstance = new TaskStatus(params)
+        if(!taskStatusInstance.hasErrors() && taskStatusInstance.save(flush: true)) {
+            flash.message = "TaskStatus ${taskStatusInstance.id} created"
+            redirect(action:show,id:taskStatusInstance.id)
+        }
+        else {
+            render(view:'create',model:[taskStatusInstance:taskStatusInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/TaskTypeController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/TaskTypeController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/TaskTypeController.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+class TaskTypeController extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ taskTypeInstanceList: TaskType.list( params ), taskTypeInstanceTotal: TaskType.count() ]
+    }
+
+    def show = {
+        def taskTypeInstance = TaskType.get( params.id )
+
+        if(!taskTypeInstance) {
+            flash.message = "TaskType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ taskTypeInstance : taskTypeInstance ] }
+    }
+
+    def delete = {
+        def taskTypeInstance = TaskType.get( params.id )
+        if(taskTypeInstance) {
+            try {
+                taskTypeInstance.delete(flush:true)
+                flash.message = "TaskType ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "TaskType ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "TaskType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def taskTypeInstance = TaskType.get( params.id )
+
+        if(!taskTypeInstance) {
+            flash.message = "TaskType not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ taskTypeInstance : taskTypeInstance ]
+        }
+    }
+
+    def update = {
+        def taskTypeInstance = TaskType.get( params.id )
+        if(taskTypeInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(taskTypeInstance.version > version) {
+                    
+                    taskTypeInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[taskTypeInstance:taskTypeInstance])
+                    return
+                }
+            }
+            taskTypeInstance.properties = params
+            if(!taskTypeInstance.hasErrors() && taskTypeInstance.save(flush: true)) {
+                flash.message = "TaskType ${params.id} updated"
+                redirect(action:show,id:taskTypeInstance.id)
+            }
+            else {
+                render(view:'edit',model:[taskTypeInstance:taskTypeInstance])
+            }
+        }
+        else {
+            flash.message = "TaskType not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def taskTypeInstance = new TaskType()
+        taskTypeInstance.properties = params
+        return ['taskTypeInstance':taskTypeInstance]
+    }
+
+    def save = {
+        def taskTypeInstance = new TaskType(params)
+        if(!taskTypeInstance.hasErrors() && taskTypeInstance.save(flush: true)) {
+            flash.message = "TaskType ${taskTypeInstance.id} created"
+            redirect(action:show,id:taskTypeInstance.id)
+        }
+        else {
+            render(view:'create',model:[taskTypeInstance:taskTypeInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/controllers/UnitOfMeasureDetailedController.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/controllers/UnitOfMeasureDetailedController.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/controllers/UnitOfMeasureDetailedController.groovy	(revision 753)
@@ -0,0 +1,110 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager'])
+class UnitOfMeasureDetailedController extends BaseController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ unitOfMeasureInstanceList: UnitOfMeasure.list( params ), unitOfMeasureInstanceTotal: UnitOfMeasure.count() ]
+    }
+
+    def show = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Show)
+            params.action='show'
+
+        def unitOfMeasureInstance = UnitOfMeasure.get( params.id )
+
+        if(!unitOfMeasureInstance) {
+            flash.message = "UnitOfMeasure not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else { return [ unitOfMeasureInstance : unitOfMeasureInstance ] }
+    }
+
+    def delete = {
+        def unitOfMeasureInstance = UnitOfMeasure.get( params.id )
+        if(unitOfMeasureInstance) {
+            try {
+                unitOfMeasureInstance.delete(flush:true)
+                flash.message = "UnitOfMeasure ${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "UnitOfMeasure ${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "UnitOfMeasure not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+
+        // In the case of an actionSubmit button, rewrite action name from 'index'.
+        if(params._action_Edit)
+            params.action='edit'
+
+        def unitOfMeasureInstance = UnitOfMeasure.get( params.id )
+
+        if(!unitOfMeasureInstance) {
+            flash.message = "UnitOfMeasure not found with id ${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ unitOfMeasureInstance : unitOfMeasureInstance ]
+        }
+    }
+
+    def update = {
+        def unitOfMeasureInstance = UnitOfMeasure.get( params.id )
+        if(unitOfMeasureInstance) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(unitOfMeasureInstance.version > version) {
+                    
+                    unitOfMeasureInstance.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[unitOfMeasureInstance:unitOfMeasureInstance])
+                    return
+                }
+            }
+            unitOfMeasureInstance.properties = params
+            if(!unitOfMeasureInstance.hasErrors() && unitOfMeasureInstance.save(flush: true)) {
+                flash.message = "UnitOfMeasure ${params.id} updated"
+                redirect(action:show,id:unitOfMeasureInstance.id)
+            }
+            else {
+                render(view:'edit',model:[unitOfMeasureInstance:unitOfMeasureInstance])
+            }
+        }
+        else {
+            flash.message = "UnitOfMeasure not found with id ${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def unitOfMeasureInstance = new UnitOfMeasure()
+        unitOfMeasureInstance.properties = params
+        return ['unitOfMeasureInstance':unitOfMeasureInstance]
+    }
+
+    def save = {
+        def unitOfMeasureInstance = new UnitOfMeasure(params)
+        if(!unitOfMeasureInstance.hasErrors() && unitOfMeasureInstance.save(flush: true)) {
+            flash.message = "UnitOfMeasure ${unitOfMeasureInstance.id} created"
+            redirect(action:show,id:unitOfMeasureInstance.id)
+        }
+        else {
+            render(view:'create',model:[unitOfMeasureInstance:unitOfMeasureInstance])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/Address.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Address.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Address.groovy	(revision 753)
@@ -0,0 +1,36 @@
+class Address {
+
+    AddressType addressType
+
+    Supplier supplier
+    Person person
+    Site site
+
+    String street1 = ''
+    String street2 = ''
+    String city = ''
+    String state = ''
+    String postCode = ''
+    String country = ''
+
+//     hasMany = []
+
+    static belongsTo = [Supplier, Person, Site]
+
+    static constraints = {
+        street1(blank:false,maxSize:50)
+        street2(maxSize:50)
+        city(blank:false,maxSize:50)
+        state(blank:false,maxSize:50)
+        postCode(blank:false,maxSize:50)
+        country(blank:false,maxSize:50)
+        supplier(nullable:true)
+        person(nullable:true)
+        site(nullable:true)
+    }
+
+    String toString() {
+        "${this.addressType}: ${this.street1}, ${this.city}"
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/domain/AddressType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/AddressType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/AddressType.groovy	(revision 753)
@@ -0,0 +1,16 @@
+class AddressType {
+    String name
+    String description = ""
+    boolean isActive = true
+
+//     static hasMany = [ : ]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/AppConfig.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/AppConfig.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/AppConfig.groovy	(revision 753)
@@ -0,0 +1,19 @@
+/**
+ * Domain class that stores various application configuration (settings) in the database.
+ * Use AppConfigService to interact with the instances.
+ */
+class AppConfig {
+    String name
+    String value
+    String description = ''
+
+    static constraints = {
+        name(maxSize:100,unique:true,blank:false)
+        value(maxSize:500,blank:false)
+        description(maxSize:500)
+    }
+
+    String toString() {
+        "${this.name} = ${this.value}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/Asset.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Asset.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Asset.groovy	(revision 753)
@@ -0,0 +1,67 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
+class Asset {
+
+    Section section
+
+    String name
+    String description = ""
+    String comment = ""
+    boolean isActive = true
+
+    static hasMany = [assetSubItems: AssetSubItem,
+                                    maintenanceActions: MaintenanceAction,
+                                    assetExtendedAttributes: AssetExtendedAttribute]
+
+    static belongsTo = [Section]
+
+    static constraints = {
+        name(maxSize:50, unique:true, blank:false)
+        description(maxSize:75)
+        comment(maxSize:500)
+        isActive()
+        section()
+    }
+
+    static mapping = {
+        assetSubItems(batchSize:1000)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+
+    static searchable = {
+        root false // only index as a component of InventoryItem.
+        only = ['name', 'description', 'comment']
+    }
+
+    def afterUpdate = {
+        // Update the Inventory searchable index, since cascading in searchable-0.5.5 is broken.
+        if(ConfigurationHolder.config.appSearchable.cascadeOnUpdate) {
+            try {
+                InventoryIndexJob.triggerNow(['calledBy':'Asset afterUpdate{}'])
+            }
+            catch(e) {log.error e}
+        } // if
+    } // afterUpdate
+
+    //  This additional setter is used to convert the checkBoxList string or string array
+    //  of ids selected to the corresponding domain objects.
+    public void setAssetSubItemsFromCheckBoxList(ids) {
+        def idList = []
+        if(ids instanceof String) {
+                if(ids.isInteger())
+                    idList << ids.toLong()
+        }
+        else {
+            ids.each() {
+                if(it.isInteger())
+                    idList << it.toLong()
+            }
+        }
+        this.assetSubItems = idList.collect { AssetSubItem.get( it ) }
+    }
+
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/AssetExtendedAttribute.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/AssetExtendedAttribute.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/AssetExtendedAttribute.groovy	(revision 753)
@@ -0,0 +1,22 @@
+class AssetExtendedAttribute {
+
+    ExtendedAttributeType extendedAttributeType
+    Asset asset
+
+    String value
+    boolean isActive = true
+
+//     static hasMany = []
+
+    static belongsTo = [Asset]
+
+    static constraints = {
+        value(blank:false, maxSize:100)
+        isActive()
+    }
+
+    String toString() {
+        "${extendedAttributeType.name}: ${this.value}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/AssetSubItem.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/AssetSubItem.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/AssetSubItem.groovy	(revision 753)
@@ -0,0 +1,33 @@
+class AssetSubItem {
+
+    AssetSubItem parentItem
+
+    String name
+    String description = ""
+    String comment = ""
+    boolean isActive = true
+
+    static hasMany = [assets: Asset,
+                                subItems: AssetSubItem,
+                                maintenanceActions: MaintenanceAction,
+                                assetSubItemExtendedAttributes: AssetSubItemExtendedAttribute]
+
+    static belongsTo = [Asset, AssetSubItem]
+
+    static constraints = {
+        name(maxSize:50, unique:true, blank:false)
+        description(maxSize:75)
+        comment(maxSize:500)
+        isActive()
+        parentItem(nullable:true)
+    }
+
+    static mapping = {
+        subItems(batchSize:1000)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/AssetSubItemExtendedAttribute.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/AssetSubItemExtendedAttribute.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/AssetSubItemExtendedAttribute.groovy	(revision 753)
@@ -0,0 +1,22 @@
+class AssetSubItemExtendedAttribute {
+
+    ExtendedAttributeType extendedAttributeType
+    AssetSubItem assetSubItem
+
+    String value
+    boolean isActive = true
+
+//     static hasMany = []
+
+    static belongsTo = [AssetSubItem]
+
+    static constraints = {
+        value(blank:false, maxSize:100)
+        isActive()
+    }
+
+    String toString() {
+        "${extendedAttributeType.name}: ${this.value}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/AssignedGroup.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/AssignedGroup.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/AssignedGroup.groovy	(revision 753)
@@ -0,0 +1,18 @@
+class AssignedGroup {
+
+    PersonGroup personGroup
+    Task task
+    Integer estimatedHour = 0
+    Integer estimatedMinute = 0
+
+    static constraints = {
+        task()
+        personGroup()
+        estimatedHour(min:0)
+        estimatedMinute(min:0,max:59)
+    }
+
+    String toString() {
+        "${personGroup.name} - ${estimatedHour}h : ${estimatedMinute}min"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/AssignedPerson.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/AssignedPerson.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/AssignedPerson.groovy	(revision 753)
@@ -0,0 +1,18 @@
+class AssignedPerson {
+
+    Person person
+    Task task
+    Integer estimatedHour = 0
+    Integer estimatedMinute = 0
+
+    static constraints = {
+        task()
+        person()
+        estimatedHour(min:0)
+        estimatedMinute(min:0,max:59)
+    }
+
+    String toString() {
+        "${person.firstName} ${person.lastName} - ${estimatedHour}h : ${estimatedMinute}min"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/Authority.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Authority.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Authority.groovy	(revision 753)
@@ -0,0 +1,18 @@
+class Authority {
+
+    static hasMany = [persons: Person]
+
+    /** description */
+    String description
+    /** ROLE String */
+    String authority
+
+    static constraints = {
+        authority(blank: false, unique: true)
+        description()
+    }
+
+    String toString() {
+        "${this.authority}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/Contact.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Contact.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Contact.groovy	(revision 753)
@@ -0,0 +1,27 @@
+class Contact {
+
+    ContactType contactType
+
+    Supplier supplier
+    Person person
+    Site site
+
+    String value
+
+//     hasMany = []
+
+    static belongsTo = [Supplier, Person, Site]
+
+    static constraints = {
+        value(maxSize:50)
+
+        supplier(nullable:true)
+        person(nullable:true)
+        site(nullable:true)
+    }
+
+    String toString() {
+        "${this.contactType}: ${this.value}"
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/domain/ContactType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/ContactType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/ContactType.groovy	(revision 753)
@@ -0,0 +1,16 @@
+class ContactType {
+    String name
+    String description = ""
+    boolean isActive = true
+
+//     static hasMany = [ : ]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/CostCode.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/CostCode.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/CostCode.groovy	(revision 753)
@@ -0,0 +1,32 @@
+class CostCode {
+
+    PurchasingGroup purchasingGroup
+
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [inventoryItemPurchases: InventoryItemPurchase]
+
+    static constraints = {
+        name(blank:false, maxSize:50, validator: {val, obj ->
+            // Name must be unique for a purchasingGroup.
+            def list = CostCode.withCriteria {
+                eq('purchasingGroup', obj.purchasingGroup)
+                eq('name', obj.name)
+                if(obj.id)
+                    notEqual('id', obj.id)
+            }
+            if(list.size() > 0)
+                return 'not.unique.for.purchasing.group'
+            // Success.
+            return true
+        })
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}.${this.purchasingGroup}"
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/domain/Department.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Department.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Department.groovy	(revision 753)
@@ -0,0 +1,25 @@
+class Department {
+
+    String name
+    String description = ""
+    String comment = ""
+    boolean isActive = true
+
+    static hasMany = [sections: Section,
+                                departmentExtendedAttributes: DepartmentExtendedAttribute,
+                                persons: Person]
+
+//     static belongsTo = []
+
+    static constraints = {
+        name(maxSize:50, unique:true, blank:false)
+        description(maxSize:75)
+        comment(maxSize:500)
+        isActive()
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/DepartmentExtendedAttribute.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/DepartmentExtendedAttribute.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/DepartmentExtendedAttribute.groovy	(revision 753)
@@ -0,0 +1,22 @@
+class DepartmentExtendedAttribute {
+
+    ExtendedAttributeType extendedAttributeType
+    Department department
+
+    String value
+    boolean isActive = true
+
+//     static hasMany = []
+
+    static belongsTo = [Department]
+
+    static constraints = {
+        value(maxSize:100)
+        isActive()
+    }
+
+    String toString() {
+        "${extendedAttributeType.name}: ${this.value}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/Entry.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Entry.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Entry.groovy	(revision 753)
@@ -0,0 +1,32 @@
+class Entry {
+    Person enteredBy
+    Task task
+    EntryType entryType
+    ProductionReference productionReference
+
+    String comment
+    Date dateDone = new Date()
+    Date dateEntered = new Date()
+    Integer durationHour = 0
+    Integer durationMinute = 0
+
+    static belongsTo = [EntryType, Task, Person]
+
+    static constraints = {
+        task()
+        comment(blank:false,maxSize:500)
+        dateDone()
+        durationHour(min:0,max:16)
+        durationMinute(min:0,max:59)
+        productionReference(nullable: true)
+    }
+
+    String toString() {
+        "${this.comment} - ${this.enteredBy}, ${this.dateDone}"
+    }
+
+    String toShortString() {
+        "${enteredBy.firstName} ${enteredBy.lastName} - ${durationHour}h : ${durationMinute}min"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/EntryType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/EntryType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/EntryType.groovy	(revision 753)
@@ -0,0 +1,16 @@
+class EntryType {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [entries: Entry]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/ExtendedAttributeType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/ExtendedAttributeType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/ExtendedAttributeType.groovy	(revision 753)
@@ -0,0 +1,21 @@
+class ExtendedAttributeType {
+
+    String name
+    String description = ""
+    boolean isActive = true
+
+//     static hasMany = []
+
+//     static belongsTo = []
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+        isActive()
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/Image.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Image.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Image.groovy	(revision 753)
@@ -0,0 +1,52 @@
+class Image implements Comparable {
+
+    Picture picture
+    Integer size
+    byte[] data
+    String contentType
+    Integer width
+    Integer height
+    Date dateCreated = new Date()
+    Date lastUpdated = new Date()
+
+    static belongsTo = [ Picture ]
+
+    static mapping = {
+        picture index: 'images_index', unique: true
+        size index: 'images_index', unique: true
+        data type: 'binary'
+    }
+
+    static constraints = {
+        data(maxSize: MAX_SIZE)
+    }
+
+    static final Integer MAX_SIZE = 10 * 1024 * 1024
+
+    static final Integer Original = 1
+    static final Integer Large = 2
+    static final Integer Medium = 3
+    static final Integer Small = 4
+
+    static final Integer[] Widths =  [ 0, 0, 500, 250, 100 ]
+    static final Integer[] Heights = [ 0, 0, 500, 250, 100 ]
+
+    static final String[] Names = [ '', 'Original', 'Large', 'Medium', 'Small' ]
+
+    int compareTo(obj) {
+        size.compareTo(obj.size)
+    }
+
+    String filename() {
+        Image.filename(picture.id, size)
+    }
+
+    static String filename(long id, int size) {
+        if (size == Original) {
+            return "${id}-${Names[size]}.jpg"
+        }
+        else {
+            return "${id}-${Names[size]}.png"
+        }
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/InventoryGroup.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/InventoryGroup.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/InventoryGroup.groovy	(revision 753)
@@ -0,0 +1,32 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
+class InventoryGroup {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [inventoryItems : InventoryItem]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {"${this.name}"}
+
+    static searchable = {
+        root false // only index as a component of InventoryItem.
+        only = ['name']
+    }
+
+    def afterUpdate = {
+        // Update the Inventory searchable index, since cascading in searchable-0.5.5 is broken.
+        if(ConfigurationHolder.config.appSearchable.cascadeOnUpdate) {
+            try {
+                InventoryIndexJob.triggerNow(['calledBy':'InventoryGroup afterUpdate{}'])
+            }
+            catch(e) {log.error e}
+        } // if
+    } // afterUpdate
+
+}
Index: branches/features/taskProcedureRework/grails-app/domain/InventoryItem.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/InventoryItem.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/InventoryItem.groovy	(revision 753)
@@ -0,0 +1,96 @@
+class  InventoryItem {
+    InventoryGroup inventoryGroup
+    InventoryType inventoryType
+    UnitOfMeasure unitOfMeasure
+    InventoryLocation inventoryLocation
+    Picture picture
+    Supplier preferredSupplier
+    String name
+    String description = ""
+    String comment = ""
+    BigDecimal estimatedUnitPriceAmount
+    Currency estimatedUnitPriceCurrency
+    String suppliersPartNumber
+    Integer unitsInStock = 0
+    Integer reorderPoint = 0
+    Integer reorderQuantity = 1
+    boolean isActive = true
+    boolean isObsolete = false
+    boolean enableReorderListing = true
+
+    static mapping = {
+        picture cascade: 'all-delete-orphan', lazy: true, inverse: true
+    }
+
+    static hasMany = [spareFor: Asset,
+                                    inventoryMovements: InventoryMovement,
+                                    alternateSuppliers: Supplier]
+
+//     static belongsTo = []
+
+    static constraints = {
+        picture(nullable:true)
+        name(unique:true, blank:false, maxSize:50)
+        description(maxSize:255)
+        comment(maxSize:500)
+        unitsInStock(min:0)
+        unitOfMeasure()
+        inventoryLocation()
+        inventoryGroup()
+        inventoryType()
+        isActive()
+        isObsolete()
+        enableReorderListing()
+        reorderPoint(min:0)
+        reorderQuantity(min:1)
+        estimatedUnitPriceAmount(nullable:true, max: new BigDecimal(1000000000000))
+        estimatedUnitPriceCurrency(nullable:true)
+        suppliersPartNumber(blank:true, nullable:true, maxSize:50)
+        preferredSupplier(nullable:true)
+    }
+
+    String toString() {"${this.name}"}
+
+    static searchable = {
+        only = ['name', 'description', 'comment', 'isActive', 'isObsolete', 'inventoryLocation', 'inventoryGroup', 'spareFor']
+        //name boost: 1.5
+        inventoryLocation component: true
+        inventoryGroup component: true
+        spareFor component: true
+    }
+
+    //  This additional setter is used to convert the checkBoxList string or string array
+    //  of ids selected to the corresponding domain objects.
+    public void setAlternateSuppliersFromCheckBoxList(ids) {
+        def idList = []
+        if(ids instanceof String) {
+                if(ids.isInteger())
+                    idList << ids.toLong()
+        }
+        else {
+            ids.each() {
+                if(it.isInteger())
+                    idList << it.toLong()
+            }
+        }
+        this.alternateSuppliers = idList.collect { Supplier.get( it ) }
+    }
+
+    //  This additional setter is used to convert the checkBoxList string or string array
+    //  of ids selected to the corresponding domain objects.
+    public void setSpareForFromCheckBoxList(ids) {
+        def idList = []
+        if(ids instanceof String) {
+                if(ids.isInteger())
+                    idList << ids.toLong()
+        }
+        else {
+            ids.each() {
+                if(it.isInteger())
+                    idList << it.toLong()
+            }
+        }
+        this.spareFor = idList.collect { Asset.get( it ) }
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/domain/InventoryItemPurchase.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/InventoryItemPurchase.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/InventoryItemPurchase.groovy	(revision 753)
@@ -0,0 +1,58 @@
+class InventoryItemPurchase {
+
+    Person enteredBy
+    Person lastUpdatedBy
+    InventoryItem inventoryItem
+    CostCode costCode
+    InventoryItemPurchaseType inventoryItemPurchaseType
+    Supplier supplier
+    TaskBudgetStatus taskBudgetStatus
+
+    Date date = new Date()
+    Date lastUpdated // autoTimestamp
+    Date dateCreated // autoTimestamp
+
+    Integer quantity
+    String purchaseOrderNumber = ''
+    BigDecimal orderValueAmount
+    Currency orderValueCurrency
+    String invoiceNumber = ''
+    String comment = ""
+
+    Boolean receivedComplete = false
+    Boolean invoicePaymentApproved = false
+
+//     hasMany = []
+
+    static belongsTo = [InventoryItem]
+
+    static constraints = {
+        quantity(min:0)
+        purchaseOrderNumber(blank:false, maxSize:50, validator: {val, obj ->
+            // For orders the purchaseOrderNumber must be unique for an inventoryItem.
+            if(obj.inventoryItemPurchaseType.id == 1L) {
+                def list = InventoryItemPurchase.withCriteria {
+                    eq('inventoryItem', obj.inventoryItem)
+                    eq('purchaseOrderNumber', obj.purchaseOrderNumber)
+                    eq('inventoryItemPurchaseType', obj.inventoryItemPurchaseType)
+                    if(obj.id)
+                        notEqual('id', obj.id)
+                }
+                if(list.size() > 0)
+                    return 'not.unique.for.inventory.item.order'
+            }
+            // Success.
+            return true
+        })
+        invoiceNumber(maxSize:50)
+        orderValueAmount(max: new BigDecimal(1000000000000))
+        orderValueCurrency()
+        comment(maxSize:255)
+        lastUpdatedBy(nullable: true)
+    }
+
+    String toString() {
+        "${this.quantity} x ${inventoryItem} - ${this.inventoryItemPurchaseType} "
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/domain/InventoryItemPurchaseType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/InventoryItemPurchaseType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/InventoryItemPurchaseType.groovy	(revision 753)
@@ -0,0 +1,16 @@
+class InventoryItemPurchaseType {
+    String name
+    String description = ""
+    boolean isActive = true
+
+//     static hasMany = []
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/InventoryLocation.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/InventoryLocation.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/InventoryLocation.groovy	(revision 753)
@@ -0,0 +1,36 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
+class InventoryLocation {
+
+    InventoryStore inventoryStore
+    String name
+    Boolean isActive = true
+
+    static hasMany = [inventoryItems: InventoryItem]
+
+//     static belongsTo = [InventoryStore]
+
+    static constraints = {
+        name(maxSize:50)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+
+    static searchable = {
+        root false // only index as a component of InventoryItem.
+        only = ['name']
+    }
+
+    def afterUpdate = {
+        // Update the Inventory searchable index, since cascading in searchable-0.5.5 is broken.
+        if(ConfigurationHolder.config.appSearchable.cascadeOnUpdate) {
+            try {
+                InventoryIndexJob.triggerNow(['calledBy':'InventoryLocation afterUpdate{}'])
+            }
+            catch(e) {log.error e}
+        } // if
+    } // afterUpdate
+
+}
Index: branches/features/taskProcedureRework/grails-app/domain/InventoryMovement.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/InventoryMovement.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/InventoryMovement.groovy	(revision 753)
@@ -0,0 +1,24 @@
+class InventoryMovement {
+    Person person
+    InventoryItem inventoryItem
+    InventoryMovementType inventoryMovementType
+    Task task
+    Integer quantity
+    Date date = new Date()
+
+    // We do not want deletion of inventory items to cascade.
+    //static belongsTo = [InventoryItem]
+
+    static constraints = {
+        inventoryItem()
+        quantity(min:1)
+        inventoryMovementType()
+        task(nullable:true)
+        person()
+        date()
+    }
+
+    String toString() {
+        "${this.quantity} ${inventoryMovementType.name} on ${date.format('EEE, dd-MMM-yyyy')} by ${person}."
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/InventoryMovementType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/InventoryMovementType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/InventoryMovementType.groovy	(revision 753)
@@ -0,0 +1,19 @@
+class InventoryMovementType {
+    String name
+    String description = ""
+    boolean incrementsInventory = false
+    boolean isActive = true
+
+    static hasMany = [inventoryMovements: InventoryMovement]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+        incrementsInventory()
+        isActive()
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/InventoryStore.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/InventoryStore.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/InventoryStore.groovy	(revision 753)
@@ -0,0 +1,20 @@
+class InventoryStore {
+
+    Site site
+    String name
+    String description = ""
+    Boolean isActive = true
+
+    static hasMany = [inventoryLocations: InventoryLocation]
+
+    static belongsTo = [Site]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/InventoryType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/InventoryType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/InventoryType.groovy	(revision 753)
@@ -0,0 +1,16 @@
+class InventoryType {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [inventoryItems: InventoryItem]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/MaintenanceAction.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/MaintenanceAction.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/MaintenanceAction.groovy	(revision 753)
@@ -0,0 +1,33 @@
+class MaintenanceAction {
+
+    TaskProcedure taskProcedure
+    MaintenancePolicy maintenancePolicy
+    Section section
+    Asset asset
+    AssetSubItem assetSubItem
+
+    String description
+    String reasoning = ""
+    Integer procedureStepNumber
+    boolean isActive = true
+
+//     static hasMany = []
+
+//     static belongsTo = []
+
+    static constraints = {
+        section(nullable:true)
+        asset(nullable:true)
+        assetSubItem(nullable:true)
+        maintenancePolicy(nullable:true)
+        procedureStepNumber(nullable:true)
+        description()
+        reasoning()
+        isActive()
+    }
+
+    String toString() {
+        "${this.description}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/MaintenancePolicy.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/MaintenancePolicy.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/MaintenancePolicy.groovy	(revision 753)
@@ -0,0 +1,21 @@
+class MaintenancePolicy {
+
+    String name
+    String description = ""
+    boolean isActive = true
+
+//     static hasMany = [maintenanceActions: MaintenanceAction]
+
+//     static belongsTo = []
+
+    static constraints = {
+        name(maxSize:50, unique:true, blank:false)
+        description(maxSize:100)
+        isActive()
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/Period.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Period.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Period.groovy	(revision 753)
@@ -0,0 +1,16 @@
+class Period {
+
+    String period
+    boolean isActive = true
+
+//     static belongsTo = []
+
+//     static constraints = {
+// 
+//     }
+
+    String toString() {
+        "${this.period}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/Person.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Person.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Person.groovy	(revision 753)
@@ -0,0 +1,88 @@
+class Person {
+    static transients = ['pass']
+    static hasMany = [authorities: Authority,
+                        personGroups: PersonGroup,
+                        taskModifications: TaskModification,
+                        entries: Entry,
+                        tasks: Task,
+                        contacts: Contact,
+                        addresses: Address,
+                        purchasingGroups: PurchasingGroup]
+
+    static belongsTo = [Authority]
+
+    Department department
+
+    String loginName
+    String firstName
+    String lastName
+    String employeeID = ''
+
+    /* Set after login by 'welcome' action, default to 12 hours, aka "sess.setMaxInactiveInterval(seconds) */
+    Integer sessionTimeout = 43200
+
+    /** MD5 Password */
+    String password
+
+    /** enabled */
+    boolean isActive = true
+
+    /** description */
+    String description = ''
+
+    /** plain password to create a MD5 password */
+    String pass
+
+    static constraints = {
+        loginName(blank: false, unique: true, minSize:4) //minSize:7
+        firstName(blank: false)
+        lastName(blank: false)
+        employeeID()
+        description()
+        department(nullable:true)
+        isActive()
+        //Enforcing minSize on password does not work since "" gets encoded to a string.
+        password(blank: false)
+        //So we need to use pass for validation then encode it for above.
+        pass(blank: false, minSize:4) //minSize:7
+        sessionTimeout(min:60, max:43200)
+    }
+
+    //Overriding the default toString method
+    String toString() {"${this.firstName} ${this.lastName}"}
+
+    //  This additional setter is used to convert the checkBoxList string or string array
+    //  of ids selected to the corresponding domain objects.
+    public void setPersonGroupsFromCheckBoxList(ids) {
+        def idList = []
+        if(ids instanceof String) {
+                if(ids.isInteger())
+                    idList << ids.toLong()
+        }
+        else {
+            ids.each() {
+                if(it.isInteger())
+                    idList << it.toLong()
+            }
+        }
+        this.personGroups = idList.collect { PersonGroup.get( it ) }
+    }
+
+    //  This additional setter is used to convert the checkBoxList string or string array
+    //  of ids selected to the corresponding domain objects.
+    public void setPurchasingGroupsFromCheckBoxList(ids) {
+        def idList = []
+        if(ids instanceof String) {
+                if(ids.isInteger())
+                    idList << ids.toLong()
+        }
+        else {
+            ids.each() {
+                if(it.isInteger())
+                    idList << it.toLong()
+            }
+        }
+        this.purchasingGroups = idList.collect { PurchasingGroup.get( it ) }
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/domain/PersonGroup.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/PersonGroup.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/PersonGroup.groovy	(revision 753)
@@ -0,0 +1,19 @@
+class PersonGroup {
+    PersonGroupType personGroupType
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [persons : Person]
+
+    static belongsTo = [Person]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/PersonGroupType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/PersonGroupType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/PersonGroupType.groovy	(revision 753)
@@ -0,0 +1,16 @@
+class PersonGroupType {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [personGroups : PersonGroup]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/Picture.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Picture.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Picture.groovy	(revision 753)
@@ -0,0 +1,32 @@
+class Picture {
+
+    InventoryItem inventoryItem
+    SortedSet images
+    String file
+    Integer operation
+    String contentType
+    Integer width
+    Integer height
+    Date dateCreated = new Date()
+    Date lastUpdated = new Date()
+
+    static belongsTo = [ InventoryItem ]
+    static hasMany = [ images : Image ]
+
+    static transients = [ 'file', 'operation']
+
+    static constraints = {
+    }
+
+    static mapping = {
+        images cascade: 'all-delete-orphan', inverse: true
+    }
+
+    static final Integer NoOp = 0
+    static final Integer RotateClockWise90 = 1
+    static final Integer RotateAntiClockWise90 = 2
+    static final Integer Rotate180 = 3
+    static final Integer Flip = 4
+    static final Integer Flop = 5
+
+}
Index: branches/features/taskProcedureRework/grails-app/domain/ProductionReference.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/ProductionReference.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/ProductionReference.groovy	(revision 753)
@@ -0,0 +1,20 @@
+class ProductionReference {
+
+    String name
+    String description = ""
+    Boolean isActive = true
+
+//     static hasMany = []
+
+//     static belongsTo = []
+
+    static constraints = {
+        name(maxSize:50, unique:true, blank:false)
+        description(maxSize:75)
+        isActive()
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/PurchasingGroup.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/PurchasingGroup.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/PurchasingGroup.groovy	(revision 753)
@@ -0,0 +1,19 @@
+class PurchasingGroup {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [persons : Person,
+                                    costCodes: CostCode]
+
+    static belongsTo = [Person]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/Section.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Section.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Section.groovy	(revision 753)
@@ -0,0 +1,32 @@
+class Section {
+
+    Site site
+    Department department
+
+    String name
+    String description = ""
+    String comment = ""
+    boolean isActive = true
+
+    static hasMany = [assets: Asset,
+                                maintenanceActions: MaintenanceAction,
+                                sectionExtendedAttributes: SectionExtendedAttribute]
+
+    static belongsTo = [Site]
+
+    static constraints = {
+        name(maxSize:50, unique:true, blank:false)
+        description(maxSize:75)
+        comment(maxSize:500)
+        isActive()
+    }
+
+    static mapping = {
+        assets(batchSize:1000)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/SectionExtendedAttribute.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/SectionExtendedAttribute.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/SectionExtendedAttribute.groovy	(revision 753)
@@ -0,0 +1,22 @@
+class SectionExtendedAttribute {
+
+    ExtendedAttributeType extendedAttributeType
+    Section section
+
+    String value
+    boolean isActive = true
+
+//     static hasMany = []
+
+    static belongsTo = [Section]
+
+    static constraints = {
+        value(maxSize:100)
+        isActive()
+    }
+
+    String toString() {
+        "${extendedAttributeType.name}: ${this.value}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/Site.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Site.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Site.groovy	(revision 753)
@@ -0,0 +1,30 @@
+class Site {
+
+    String name
+    String description = ""
+    String comment = ""
+    Boolean isActive = true
+
+    static hasMany = [sections: Section,
+                                siteExtendedAttributes: SiteExtendedAttribute,
+                                inventoryStores: InventoryStore,
+                                contacts: Contact,
+                                addresses: Address]
+
+//     static belongsTo = []
+
+    static constraints = {
+        name(maxSize:50, unique:true, blank:false)
+        description(maxSize:75)
+        comment(maxSize:500)
+        isActive()
+    }
+
+    static mapping = {
+        sections(batchSize:1000)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/SiteExtendedAttribute.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/SiteExtendedAttribute.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/SiteExtendedAttribute.groovy	(revision 753)
@@ -0,0 +1,22 @@
+class SiteExtendedAttribute {
+
+    ExtendedAttributeType extendedAttributeType
+    Site site
+
+    String value
+    boolean isActive = true
+
+//     static hasMany = []
+
+    static belongsTo = [Site]
+
+    static constraints = {
+        value(maxSize:100)
+        isActive()
+    }
+
+    String toString() {
+        "${extendedAttributeType.name}: ${this.value}"
+    }
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/Supplier.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Supplier.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Supplier.groovy	(revision 753)
@@ -0,0 +1,20 @@
+class Supplier {
+    SupplierType supplierType
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [contacts: Contact,
+                                    addresses: Address]
+
+//     static belongsTo = []
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/SupplierType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/SupplierType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/SupplierType.groovy	(revision 753)
@@ -0,0 +1,16 @@
+class SupplierType {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [suppliers: Supplier]
+    
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/Task.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/Task.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/Task.groovy	(revision 753)
@@ -0,0 +1,64 @@
+class Task {
+
+    TaskGroup taskGroup
+    TaskStatus taskStatus
+    TaskPriority taskPriority
+    TaskBudgetStatus taskBudgetStatus
+    TaskType taskType
+    Task parentTask
+    Person leadPerson
+    Site site
+    Section section
+    Asset primaryAsset
+    AssetSubItem assetSubItem
+    TaskRecurringSchedule taskRecurringSchedule
+    TaskProcedure taskProcedure
+
+    String description
+    String comment = ""
+    Date targetStartDate = new Date()
+    Date targetCompletionDate = new Date()
+    boolean approved = false
+    boolean trash = false
+    boolean attentionFlag = false
+    boolean safetyRequirement = false
+    boolean regulatoryRequirement = false
+    boolean mandatoryRequirement = false
+    boolean positiveFault = false
+
+    static hasMany = [entries: Entry,
+                        taskModifications: TaskModification,
+                        assignedGroups: AssignedGroup,
+                        assignedPersons: AssignedPerson,
+                        subTasks: Task,
+                        associatedAssets: Asset,
+                        inventoryMovements: InventoryMovement]
+
+    static mappedBy = [taskRecurringSchedule:"task"]
+
+    static belongsTo = [TaskGroup, TaskStatus, Task, Person]
+
+    static constraints = {
+        description(blank:false,maxSize:75)
+        comment(maxSize:1000)
+        targetStartDate()
+        targetCompletionDate(validator: {val, obj ->
+            if(val.before(obj.targetStartDate))
+                return 'before.targetStartDate'
+        })
+        leadPerson()
+        taskPriority()
+        taskBudgetStatus()
+        taskStatus()
+        parentTask(nullable:true)
+        site(nullable:true)
+        section(nullable:true)
+        primaryAsset(nullable:true)
+        assetSubItem(nullable:true)
+        taskRecurringSchedule(nullable:true)
+        taskProcedure(nullable:true)
+
+    }
+
+    String toString() {"${this.id} - ${this.description}"}
+}
Index: branches/features/taskProcedureRework/grails-app/domain/TaskBudgetStatus.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/TaskBudgetStatus.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/TaskBudgetStatus.groovy	(revision 753)
@@ -0,0 +1,14 @@
+class TaskBudgetStatus {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [tasks : Task]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {"${this.name}"}
+}
Index: branches/features/taskProcedureRework/grails-app/domain/TaskGroup.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/TaskGroup.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/TaskGroup.groovy	(revision 753)
@@ -0,0 +1,14 @@
+class TaskGroup {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [tasks : Task]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {"${this.name}"}
+}
Index: branches/features/taskProcedureRework/grails-app/domain/TaskModification.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/TaskModification.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/TaskModification.groovy	(revision 753)
@@ -0,0 +1,21 @@
+class TaskModification {
+    Person person
+    TaskModificationType taskModificationType
+    Task task
+    Date date = new Date()
+    String comment = ""
+
+    static belongsTo = [Person, TaskModificationType, Task]
+
+    static constraints = {
+        person()
+        taskModificationType()
+        task()
+        date()
+        comment()
+    }
+
+    String toString() {
+        "${taskModificationType} on ${date.format('EEE, dd-MMM-yyyy')} by ${person}."
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/TaskModificationType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/TaskModificationType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/TaskModificationType.groovy	(revision 753)
@@ -0,0 +1,16 @@
+class TaskModificationType {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [taskModifications : TaskModification]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/TaskPriority.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/TaskPriority.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/TaskPriority.groovy	(revision 753)
@@ -0,0 +1,14 @@
+class TaskPriority {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [tasks : Task]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {"${this.name}"}
+}
Index: branches/features/taskProcedureRework/grails-app/domain/TaskProcedure.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/TaskProcedure.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/TaskProcedure.groovy	(revision 753)
@@ -0,0 +1,19 @@
+class TaskProcedure {
+
+    String name
+    String description = ""
+    Boolean isActive = true
+
+    static hasMany = [tasks: Task, maintenanceActions: MaintenanceAction]
+
+//     static belongsTo = []
+
+    static constraints = {
+        name(maxSize:75,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/domain/TaskRecurringSchedule.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/TaskRecurringSchedule.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/TaskRecurringSchedule.groovy	(revision 753)
@@ -0,0 +1,108 @@
+import org.codehaus.groovy.runtime.TimeCategory
+// the above will be deprecated and replaced by: groovy.time.TimeCategory
+
+class TaskRecurringSchedule {
+
+    Task lastGeneratedSubTask
+    Period recurPeriod
+    Period taskDurationPeriod
+
+    Integer recurEvery = 1
+    Integer taskDuration = 0
+    Integer generateAhead = 1
+    Integer subTasksGenerated = 0
+    Integer maxSubTasks = 0
+    Date nextGenerationDate = new Date()
+    Date nextTargetStartDate = new Date()+1
+    Date nextTargetCompletionDate = new Date()
+    boolean enabled = true
+    boolean useTargetCompletionDate = false
+
+//     static hasMany = []
+
+    static belongsTo = [task: Task]
+
+    static constraints = {
+        recurEvery(min:1, max:365)
+        taskDuration(min:0, max:365)
+        generateAhead(min:0, max:62)
+        lastGeneratedSubTask(nullable:true)
+    }
+
+    String toString() {
+        "Recur every ${recurEvery} ${recurPeriod}"
+    }
+
+    // Events do not fire/pass before validation, since they are called during flushing.
+    // Defaults set above to pass validation.
+    def beforeInsert = {
+        setNextGenerationDate()
+        setNextTargetCompletionDate()
+    }
+
+    public void setNextTargetStartDate() {
+        switch (recurPeriod.period) {
+            case "Day(s)":
+                use(TimeCategory) {
+                    nextTargetStartDate = nextTargetStartDate + recurEvery.days
+                }
+                break
+            case "Week(s)":
+                use(TimeCategory) {
+                    nextTargetStartDate = nextTargetStartDate + recurEvery.weeks
+                }
+                break
+            case "Month(s)":
+                use(TimeCategory) {
+                    nextTargetStartDate = nextTargetStartDate + recurEvery.months
+                }
+                break
+            case "Year(s)":
+                use(TimeCategory) {
+                    nextTargetStartDate = nextTargetStartDate + recurEvery.years
+                }
+                break
+        default:
+                log.error "No case for recurPeriod.period: ${recurPeriod.period}"
+                break
+        }
+    }
+
+    public void setNextGenerationDate() {
+        use(TimeCategory) {
+            nextGenerationDate = nextTargetStartDate - generateAhead.days
+        }
+        def now = new Date()
+        if( nextGenerationDate < now) {nextGenerationDate = now}
+    }
+
+    public void setNextTargetCompletionDate() {
+        switch (taskDurationPeriod.period) {
+            case "Day(s)":
+                use(TimeCategory) {
+                    nextTargetCompletionDate = nextTargetStartDate + taskDuration.days
+                }
+                break
+            case "Week(s)":
+                use(TimeCategory) {
+                    nextTargetCompletionDate = nextTargetStartDate + taskDuration.weeks
+                }
+                break
+            case "Month(s)":
+                use(TimeCategory) {
+                    nextTargetCompletionDate = nextTargetStartDate + taskDuration.months
+                }
+                break
+            case "Year(s)":
+                use(TimeCategory) {
+                    nextTargetCompletionDate = nextTargetStartDate + taskDuration.years
+                }
+                break
+            default:
+                log.error "No case for taskDurationPeriod.period: ${taskDurationPeriod.period}"
+                break
+        }
+    }
+
+}
+
Index: branches/features/taskProcedureRework/grails-app/domain/TaskStatus.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/TaskStatus.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/TaskStatus.groovy	(revision 753)
@@ -0,0 +1,14 @@
+class TaskStatus {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [tasks : Task]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {"${this.name}"}
+}
Index: branches/features/taskProcedureRework/grails-app/domain/TaskType.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/TaskType.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/TaskType.groovy	(revision 753)
@@ -0,0 +1,14 @@
+class TaskType {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [tasks : Task]
+
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {"${this.name}"}
+}
Index: branches/features/taskProcedureRework/grails-app/domain/UnitOfMeasure.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/domain/UnitOfMeasure.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/domain/UnitOfMeasure.groovy	(revision 753)
@@ -0,0 +1,16 @@
+class UnitOfMeasure {
+    String name
+    String description = ""
+    boolean isActive = true
+
+    static hasMany = [inventoryItems: InventoryItem]
+    
+    static constraints = {
+        name(maxSize:50,unique:true,blank:false)
+        description(maxSize:100)
+    }
+
+    String toString() {
+        "${this.name}"
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/i18n/jasper.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/jasper.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/jasper.properties	(revision 753)
@@ -0,0 +1,4 @@
+jasper.controller.invalidFormat = Invalid format: {0}
+
+jasper.taglib.missingAttribute = Missing required attribute: {0}.  All of the following attributes are required: {1}.
+jasper.taglib.invalidFormatAttribute = Value {0} is an invalid format attribute.  Only {1} are permitted.
Index: branches/features/taskProcedureRework/grails-app/i18n/messages.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages.properties	(revision 753)
@@ -0,0 +1,494 @@
+#
+# Custom and domain constraint messages.
+#
+
+address.owner.not.found=An owner (Person, Site or Supplier) must be supplied to create an address.
+contact.owner.not.found=An owner (Person, Site or Supplier) must be supplied to create contact details.
+
+asset.tree.import.success=Asset tree imported.
+asset.tree.import.failure=Could not create asset tree from supplied file, failed on line {0}, see {1}.
+
+inventory.import.success=Inventory imported.
+inventory.import.failure=Could not create inventory from supplied file, failed on line {0}, see {1}.
+
+inventoryItemPictures.import.success=Inventory item pictures imported, see {0}.
+inventoryItemPictures.import.failure.no.directory=Import directory on server not found.
+inventoryItemPictures.import.failure.to.unzip=Failed to unzip supplied file.
+inventoryItemPictures.import=Picture Import
+inventoryItemPictures.import.help=A zip file of pictures (max 100MB) or singles pictures may be imported. Pictures \
+    must have the same file names as existing inventory items.
+
+inventoryItemPurchase.import.success=Inventory item purchases imported.
+inventoryItemPurchase.import.failure=Could not create inventory item purchases from supplied file, failed on line {0}, see {1}.
+
+person.import.success=Person list imported.
+person.import.failure=Could not create persons from supplied file, failed on line {0}, see {1}.
+
+asset.copy.subItem.create.failure=Could not complete operation, as sub item failed to save.
+asset.copy.subItem.too.many.failure=Could not complete operation, as there appears to be too many sub items.
+asset.copy.method.required=Please select a copy method for sub items.
+asset.copy.method=Copy Method
+asset.copy.method.help=Link creates a new asset and links it to EXISTING sub items. \
+    While copy creates a new asset and new sub items by appending '(id:#)' to create unique sub item names.
+asset.copy.asset.required=Please select an asset to copy.
+
+maintenanceActions.still.associated=Could not complete operation as maintenance actions are still associated \
+    with this item.
+maintenanceActions.still.associated.subItem=Could not complete operation as maintenance actions are still associated \
+    with a sub item.
+inventoryStores.still.associated=Could not complete operation as inventory stores are still associated with this item.
+
+site.section.delete.failure=Could not complete operation as sections failed to delete.
+section.asset.delete.failure=Could not complete operation as assets failed to delete.
+asset.subItems.delete.failure=Could not complete operation as orphan sub items failed to delete.
+
+assetSubItem.asset.not.found=Could not complete operation as an asset was supplied but not found.
+assetSubItem.assets.associated=Could not complete operation as assets are still associated with this sub item.
+
+sub.task.create.confirm=Immediately create and save a new sub task?
+
+person.pass.minSize.notmet=Password is less than the minimum size of [{3}]
+person.pass.blank=Password cannot be blank
+person.pass.doesNotMatch=Passwords must match
+
+costCode.name.not.unique.for.purchasing.group=CostCode name must be unique for purchasingGroup.
+
+#
+# Help Balloon and property definitions.
+#
+
+# Report help balloon messages.
+report.stock.take.overview=Stock Take (Overview)
+report.stock.take.overview.help=Use this report to manage inventory stock take. Use in conjunction with the Stock Take (By Location) report.
+report.stock.take.by.location=Stock Take (Location)
+report.stock.take.by.location.help=Enter a comma separated list of inventory locations. \
+    Use the Stock Take (Overview) report to get the list of locations. A % symbol may be used as a wild card, e.g: X1, X2, Y%, Z%7
+
+# Person properties.
+person.personGroups=Person Groups
+person.personGroups.help=Groups may be assigned to tasks and \
+may also provide a record of persons qualified or trained in a specific area. \
+    Groups provide no application authorisations.
+person.purchasingGroups=Purchasing Groups
+person.purchasingGroups.help=Purchasing groups determine the available cost codes that a person may purchase against.
+person.loginName=Login Name
+person.loginName.help=This is the id or name that the person will use to login to the application.
+person.firstName=First Name
+person.firstName.help=The person's real first name.
+person.lastName=Last Name
+person.lastName.help=The person's real last name.
+person.password=Password
+person.password.help=The password that the person will use to login to the application (should be changed by them later).
+person.isActive=Active
+person.isActive.help=Disable this to prevent a person logging in to the application.
+
+person.authorities=Authorities
+person.authorities.help=Give this person authority to do things in the application. \
+    The user must logout for changes to take effect.
+
+# InventoryItemPurchase properties.
+inventoryItemPurchase.purchaseOrderNumber=Purchase Order #
+inventoryItemPurchase.purchaseOrderNumber.help=This number must be exact in case and spacing. \
+    All purchase received and invoice approval requires this number to track correctly. \
+    The number may only appear once for each inventory item. \
+    To enter multiple line items for a purchase order # 'M123' use 'M123.1' and 'M123.2' for example.
+inventoryItemPurchase.order.placed.date=Date
+inventoryItemPurchase.order.placed.date.help=The date that the order was placed. \
+    May be adjusted at the end of financial years. Also see the 'date created' and 'last updated' properties.
+inventoryItemPurchase.cost.code=Cost Code
+inventoryItemPurchase.cost.code.help=Cost codes assign cost to the correct asset and accouting ledger number/account. \
+    Ideally cost codes should be asset based and reflect the asset tree.
+inventoryItemPurchase.task.budget.status=Budget Status
+inventoryItemPurchase.task.budget.status.help=Was this purchase planned for in the budget or is it an unplanned spend.
+inventoryItemPurchase.supplier=Supplier
+inventoryItemPurchase.supplier.help=The supplier to make the purchase out to.
+inventoryItemPurchase.quantity=Quantity
+inventoryItemPurchase.quantity.help=The number of inventory item units purchased.
+inventoryItemPurchase.receive.quantity=Receive Quantity
+inventoryItemPurchase.receive.quantity.help=The number of inventory item units received.
+inventoryItemPurchase.approve.quantity=Approve Quantity
+inventoryItemPurchase.approve.quantity.help=The number of inventory item units to approve payment for.
+inventoryItemPurchase.order.value=Order Value
+inventoryItemPurchase.order.value.help=The total value of this line item.
+inventoryItemPurchase.receive.value=Receive Value
+inventoryItemPurchase.receive.value.help=The value of items received.
+inventoryItemPurchase.approve.value=Approve Value
+inventoryItemPurchase.approve.value.help=The value to approve payment for.
+inventoryItemPurchase.invoice.number=Invoice Number
+inventoryItemPurchase.invoice.number.help=The invoice number that this line item approves payment for.
+
+entry.duration=Duration
+entry.duration.help=The time (hh:mm) booked against this entry for date done.
+entry.duration.fault=Down Time.
+entry.duration.fault.help=The production down time (hh:mm) directly attributable to this fault.
+entry.date.done=Date Done
+entry.date.done.help=The date on which the event actually occurred.
+entry.comment.fault=Fault
+entry.comment.fault.help=Techinical description of the fault and what is happening, NOT what needs doing!
+entry.comment.cause=Cause
+entry.comment.cause.help=The root cause of the fault. Professional opinion on any faults. \
+Include condition and contributing factors.
+entry.comment.work.done=Work Done
+entry.comment.work.done.help=Describe the work that was done.
+entry.productionReference.fault=Production Reference
+entry.productionReference.fault.help=The production during which the fault occurred.
+
+assignedGroup.estimatedDuration=Estimated Duration
+assignedGroup.estimatedDuration.help=The estimated amount of time (hh:mm) that you would \
+like to assign this group to the task.
+
+assignedPerson.estimatedDuration=Estimated Duration
+assignedPerson.estimatedDuration.help=The estimated amount of time (hh:mm) that you would \
+like to assign this person to the task.
+
+task.delete.failure.production=Tasks may not be deleted in production mode, \
+    set the trash flag instead.
+task.notFound=Could not complete operation, task not found.
+task.operationNotPermittedOnCompleteTask=This operation is not permitted on a complete task.
+task.operationNotPermittedOnTaskInTrash=This operation is not permitted on a task that is in the trash.
+task.operationNotPermittedOnRecurringTaskWithoutAuth=This operation is not permitted on a recurring task without authorisation.
+task.failedToSave=Could not complete operation, task failed to save.
+task.modifications.failedToSave=Could not complete operation, as task modification record failed to save.
+task.assignedGroups.failedToSave=Could not complete operation, as assignedGroup record failed to save.
+task.assignedPersons.failedToSave=Could not complete operation, as assignedPerson record failed to save.
+tast.taskRecurringSchedule.alreadyExists=This task already has a recurring schedule.
+task.targetCompletionDate.before.targetStartDate=The target completion date must be equal to or greater than \
+    the target start date.
+
+entry.create.no.params=Please select a task, then add an entry.
+
+taskRecurringSchedule.notFound=Could not complete operation, recurring schedule not found.
+personGroup.not.found=Person Group not found, it may have been deleted.
+person.not.found=Person record not found, it may have been deleted.
+
+# Task Properties.
+task.assignedGroups=Assigned Groups
+task.assignedGroups.help=The person groups assigned to work on this task during planning along with estimated time.
+task.assignedPersons=Assigned Persons
+task.assignedPersons.help=The persons assigned to work on this task during planning along with estimated time.
+task.description=Task Description
+task.description.help=Short basic description of the task.
+task.description.immediateCallout=Immediate Callout Description.
+task.description.immediateCallout.help=Short description of the callout from an operations perspective.
+task.comment=Task Comment
+task.comment.help=Long text for additional info, only shown in detail views.
+task.targetStartDate=Target Start Date
+task.targetStartDate.help=The date we would like the task to start, set during scheduling.
+task.targetStartDate.immediateCallout=Callout Date
+task.targetStartDate.immediateCallout.help=The date the callout occured.
+task.targetCompletionDate=Target Completion Date
+task.targetCompletionDate.help=The date we would like the task to be completed by, set during scheduling.
+task.leadPerson=Lead Person
+task.leadPerson.help=The primay contact person.
+task.safetyRequirement=Safety
+task.safetyRequirement.help=Completion of this task is required to correct an immediate safety concern. \
+    This task must be completed and is not allowed to be missed.
+task.regulatoryRequirement=Regulatory
+task.regulatoryRequirement.help=Completion of this task is a regulatory requirement. \
+    This task must be completed and is not allowed to be missed.
+task.mandatoryRequirement=Mandatory
+task.mandatoryRequirement.help=Completion of this task is mandatory, due to company policy or operational requirement. \
+    This task must be completed and is not allowed to be missed.
+task.positiveFault=Positive Fault
+task.positiveFault.help=Set false if unsure. Used to calculate preventative efficiency or P.E.
+
+# Task Actions
+task.status.resolved=Resolved.
+task.status.resolved.help=Indicate that root cause is known and has been completely resolved.
+task.status.unresolved=Unresolved.
+task.status.unresolved.help=Indicate that this task requires further attention, root cause is either unknown or unresolved.
+
+taskRecurringSchedule.nextTargetStartDate.mayNotBePast=Please select a start date that is not in the past.
+taskRecurringSchedule.nextTargetStartDate=Next Target Start Date
+taskRecurringSchedule.nextTargetStartDate.help=The target start date for the next auto generated sub task.
+taskRecurringSchedule.recurEvery=Recur Every
+taskRecurringSchedule.recurEvery.help=How often this task should recur. Determines the period between sub task target start dates.
+taskRecurringSchedule.taskDuration=Task Duration
+taskRecurringSchedule.taskDuration.help=How long to allow for the task. Determines the target completion date of the sub tasks.
+taskRecurringSchedule.generateAhead=Generate Ahead
+taskRecurringSchedule.generateAhead.help=How far ahead of the next target start date to generate sub tasks. \
+    This allows work packs to be built and work load to be seen and planned. \
+    Only generate ahead as far as short term planning is done, since all generated sub task \
+    values will be set and therefore time consuming to change.
+taskRecurringSchedule.maxSubTasks=Max Sub Tasks
+taskRecurringSchedule.maxSubTasks.help=Maximum number of sub tasks to generate. Set to 0 \
+    for no limit.
+taskRecurringSchedule.useTargetCompletionDate=Target Completion
+taskRecurringSchedule.useTargetCompletionDate.help=On to use the parent task's target completion date. \
+    Off to continue generation past the parent task's target completion date.
+taskRecurringSchedule.enabled=Enabled
+taskRecurringSchedule.enabled.help=On to enable automatic sub task generation. \
+    Off to stop automatic sub task generation. <br /><br />\
+    The system will turn this off if there are no further sub tasks to be generated.
+
+task.primaryAsset=Primary Asset
+task.primaryAsset.help=This is the asset that costs will be assigned to.
+task.associatedAssets=Associated Assets
+task.associatedAssets.help=These assets are to be associated with this task, but costs will not be assigned.
+
+# InventoryItem Properties.
+inventory.item.name=Name
+inventory.item.name.help=The inventory item's name as known on site. \
+    Also called the part number but may contain letters and numbers.
+inventory.item.description=Description
+inventory.item.description.help=The inventory item description as it would appear on a reorder.
+inventory.item.comment=Comment
+inventory.item.comment.help=Additional on site comments. Which may include additional ordering information, \
+    search key words and other useful information.
+inventory.item.estimated.unit.price.amount=Unit Price
+inventory.item.estimated.unit.price.amount.help=Estimated reorder price of a single unit.
+inventory.item.unit.of.measure=Unit Of Measure
+inventory.item.unit.of.measure.help=The units that this item will be measured in. Set once during creation \
+    and cannot be changed as changing would invalidate all movement, another item with the correct units must be created.
+inventory.item.suppliers.part.number=Part Number
+inventory.item.suppliers.part.number.help=The suppliers part number as it would appear on a reorder.
+inventory.item.units.in.stock=In Stock
+inventory.item.units.in.stock.help=Current units in stock.
+inventory.item.reorder.point=Reorder Point
+inventory.item.reorder.point.help=Point at which a reorder will be flagged.
+inventory.item.reorder.quantity=Reorder Quantity
+inventory.item.reorder.quantity.help=Typical or recommended quantity to reorder. \
+    Infers the max holding quantity (Reorder Point + Reorder Quantity). \
+    Often determined by a price break or minimum order quantity.
+inventory.item.is.active=Active
+inventory.item.is.active.help=Disable to remove from search results.
+inventory.item.is.obsolete=Obsolete
+inventory.item.is.obsolete.help=Enabled indicates that item considered obsolete by the supplier.
+inventory.item.enable.reorder.listing=Reorder Listing
+inventory.item.enable.reorder.listing.help=Enabled to show item on reorder lists.
+inventory.item.inventory.location=Location
+inventory.item.inventory.location.help=The location or bin where this item can be found.
+inventory.item.inventory.group=Group
+inventory.item.inventory.group.help=An easy way to group or place items in various piles to assit with management.
+inventory.item.inventory.type=Type
+inventory.item.inventory.type.help=The type of inventory that this item falls into.
+inventory.item.preferred.supplier=Preferred Supplier
+inventory.item.preferred.supplier.help=The preferred supplier to purchase this item from. \
+    Often determined by cost, contract or availability.
+inventory.item.alternate.suppliers=Alternate Suppliers
+inventory.item.alternate.suppliers.help=List of alternate suppliers that this item may be purchased from. \
+    For example when the preferred supplier has no stock.
+inventory.item.spare.for=Spare For
+inventory.item.spare.for.help=List of assets that this item is held as a spare for.
+
+# InventoryItem Messages.
+inventory.item.is.obsolete.message=This item has been flagged as obsolete.
+inventory.item.not.active.message=This item has been flagged as not active.
+inventory.item.reorder.not.allowed=Reorder not allowed.
+inventory.item.reorder.listing.disabled=This item has reorder listing disabled and will not appear on reorder lists.
+inventory.item.already.has.picture=Inventory item already has a picture, please delete the old picture first.
+inventory.item.picture.file.unrecognised=Image file [{0}]: type not recognised.
+inventory.item.picture.source.not.supported=Image source type not supported.
+
+inventoryMovement.quantity.insufficientItemsInStock=Could not complete operation, insufficient items in stock.
+inventoryMovement.inventoryItem.notFound=Inventory Item not found.
+inventoryMovement.still.associated=Could not complete operation as inventory movements are still associated with this item.
+
+inventoryItemPurchase.purchaseOrderNumber.not.unique.for.inventory.item.order=Purchase Order Number must be unique for this inventory item order.
+inventoryItemPurchase.invoiceNumber.required=An invoice number must be supplied to approve payment.
+inventoryItemPurchase.delete.failure.received.exists=Could not delete, items have been received.
+inventoryItemPurchase.delete.failure.payment.approved=Could not delete, payment has been approved.
+inventoryItemPurchase.operation.not.permitted.on.inactive.or.obsolete.item=This operation is not permitted on an inactive or obsolete inventory item.
+inventoryItemPurchase.costCodes.not.found=No cost codes found, a person needs to be assigned to a purchasing group that has cost codes.
+
+assignedGroup.task.not.found=Please select a task and then ''Add Assigned Group''.
+assignedPerson.task.not.found=Please select a task and then ''Add Assigned Person''.
+
+#
+# Default messages.
+#
+
+default.list.failure=Could not generate list for class {0}.
+default.not.found={0} {1} not found, it may have been deleted.
+default.delete.success={0} {1} deleted.
+default.delete.failure={0} {1} could not be deleted.
+default.update.success={0} {1} updated.
+default.update.failure={0} {1} could not be updated.
+default.create.success={0} {1} created.
+default.create.failure={0} could not be created.
+default.optimistic.locking.failure=Another user has updated this item while you were editing, please check the updated values.
+default.file.over.max.size=Supplied file is greater than max size of {0} {1}.
+default.file.not.supplied=No file supplied.
+default.file.no.header=The supplied file does not have the correct header lines, please see the template file.
+default.not.development.environment.failure=Could not complete operation, dev environment not detected.
+
+default.doesnt.match.message=Property [{0}] of class [{1}] with value [{2}] does not match the required pattern [{3}]
+default.invalid.url.message=Property [{0}] of class [{1}] with value [{2}] is not a valid URL
+default.invalid.creditCard.message=Property [{0}] of class [{1}] with value [{2}] is not a valid credit card number
+default.invalid.email.message=Property [{0}] of class [{1}] with value [{2}] is not a valid e-mail address
+default.invalid.range.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid range from [{3}] to [{4}]
+default.invalid.size.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid size range from [{3}] to [{4}]
+default.invalid.max.message=Property [{0}] of class [{1}] with value [{2}] exceeds maximum value [{3}]
+default.invalid.min.message=Property [{0}] of class [{1}] with value [{2}] is less than minimum value [{3}]
+default.invalid.max.size.message=Property [{0}] of class [{1}] with value [{2}] exceeds the maximum size of [{3}]
+default.invalid.min.size.message=Property [{0}] of class [{1}] with value [{2}] is less than the minimum size of [{3}]
+default.invalid.validator.message=Property [{0}] of class [{1}] with value [{2}] does not pass custom validation
+default.not.inlist.message=Property [{0}] of class [{1}] with value [{2}] is not contained within the list [{3}]
+default.blank.message=Property [{0}] of class [{1}] cannot be blank
+default.not.equal.message=Property [{0}] of class [{1}] with value [{2}] cannot equal [{3}]
+default.null.message=Property [{0}] of class [{1}] cannot be null
+default.not.unique.message=Property [{0}] of class [{1}] with value [{2}] must be unique
+
+default.paginate.prev=Previous
+default.paginate.prev.abbrev=Prev
+default.paginate.next=Next
+
+default.close.text=Close
+default.options.text=Options
+default.none.text=None
+default.all.text=All
+default.please.select.text=--Please-Select--
+default.none.select.text=--None--
+default.all.select.text=--All--
+
+#
+# Rich UI plugin - Calendar
+#
+
+default.time=Time
+default.week=Week
+default.monday=Mon
+default.tuesday=Tues
+default.wednesday=Wed
+default.thursday=Thu
+default.friday=Fri
+default.saturday=Sat
+default.sunday=Sun
+
+#
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+#
+
+typeMismatch.java.net.URL=Property {0} must be a valid URL
+typeMismatch.java.net.URI=Property {0} must be a valid URI
+typeMismatch.java.util.Date=Property {0} must be a valid Date
+typeMismatch.java.lang.Double=Property {0} must be a valid number
+typeMismatch.java.lang.Integer=Property {0} must be a valid number
+typeMismatch.java.lang.Long=Property {0} must be a valid number
+typeMismatch.java.lang.Short=Property {0} must be a valid number
+typeMismatch.java.math.BigDecimal=Property {0} must be a valid number
+typeMismatch.java.math.BigInteger=Property {0} must be a valid number
+
+#
+# Navigation plugin, see conf/Config.groovy for menu's.
+# Subitems are not currently resolving with this plugin.
+#
+
+navigation.nav.home=Home
+navigation.nav.home.start=Start
+navigation.nav.home.appAdmin=Admin
+navigation.nav.home.manager=Manager
+navigation.nav.home.changeSessionTimeout=Timeout
+navigation.nav.home.changePassword=Password
+
+navigation.nav.tasks=Tasks
+navigation.nav.tasks.create=Create
+navigation.nav.tasks.search=Search
+navigation.nav.tasks.show=Show
+
+navigation.nav.inventory=Inventory
+navigation.nav.assets=Assets
+
+#
+# FilterPane plugin, properties.
+#
+
+fp.property.text.associatedAssets.name=Associated Asset
+fp.property.text.primaryAsset.name=Primary Asset
+fp.property.text.trash=Trash
+fp.property.text.scheduled=Scheduled
+fp.property.text.approved=Approved
+fp.property.text.isObsolete=Obsolete
+fp.property.text.taskGroup.name=Group
+fp.property.text.taskPriority.name=Priority
+fp.property.text.taskStatus.name=Status
+fp.property.text.description=Description
+fp.property.text.comment=Comment
+fp.property.text.leadPerson.lastName=Lead Person (Last Name)
+fp.property.text.leadPerson.firstName=Lead Person (First Name)
+fp.property.text.taskType.name=Type
+fp.property.text.inventoryLocation.name=Location
+fp.property.text.spareFor.name=Spare For
+fp.property.text.supplier.name=Supplier
+fp.property.text.estimatedUnitPriceAmount=Estimated Unit Price
+
+fp.property.text.inventoryItemPurchaseType.name=Type
+
+#
+# TaskSearch Service.
+#
+
+task.search.include.completed=Incl. Completed
+task.search.include.completed.help=Include completed tasks in the results.
+
+task.search.text.all.tasks=All Tasks
+task.search.text.all.tasks.help=All tasks that are not in the trash. Tasks in the trash must be explicitly requested in the advanced search.
+task.search.text.all.tasks.message=All tasks for {0}.
+task.search.text.all.tasks.none.found=No tasks found for {0}.
+task.search.text.all.tasks.between.message=All tasks between {0} and {1}.
+task.search.text.all.tasks.between.none.found=No tasks found between {0} and {1}.
+
+task.search.text.persons.tasks=Person's Tasks
+task.search.text.persons.tasks.help=Approved tasks that a person is assigned to.
+task.search.text.persons.tasks.message=Tasks for {0} on {1}.
+task.search.text.persons.tasks.none.found=No tasks found for {0} on {1}.
+task.search.text.persons.tasks.between.message=Tasks for {0} between {1} and {2}.
+task.search.text.persons.tasks.between.none.found=No tasks found for {0} between {1} and {2}.
+
+task.search.text.my.todays=Today
+task.search.text.my.todays.description=My tasks and approved tasks that I am assigned to.
+
+task.search.text.persons.immediate.callouts=Person's Callouts
+task.search.text.persons.immediate.callouts.help=Immediate callouts by person (lead person or created by).
+task.search.text.persons.immediate.callouts.message=Immediate callouts for {0} on {1}.
+task.search.text.persons.immediate.callouts.none.found=No immediate callouts found for {0} on {1}.
+task.search.text.persons.immediate.callouts.between.message=Immediate callouts for {0} between {1} and {2}.
+task.search.text.persons.immediate.callouts.between.none.found=No immediate callouts found for {0} between {1} and {2}.
+
+task.search.calendar.text.too.many.results=Too many results, only {0} are shown.
+task.search.text.work.done=Work Done
+task.search.text.work.done.description=Work done by person and date.
+task.search.text.work.done.message=Work done by {0} on {1}.
+task.search.text.work.done.none.found=No entries found for {0} on {1}.
+task.search.text.work.load=Work Load
+task.search.text.work.load.description=Work load by group and date.
+task.search.text.work.load.message=Work load between {0} and {1}.
+task.search.text.work.load.none.found=No tasks found between {0} and {1}.
+task.search.text.work.load.too.many.results=Too many tasks found to perform calculatation, {0} / {1} shown.
+
+#
+# InventoryItemSearch
+#
+
+inventoryItem.search.searchText=Search
+inventoryItem.search.searchText.help=By default all words are matched and results are sorted by relevance. \
+    A * symbol may be used as a wild card, e.g: '2305*' would find 2305RS and 2305-RS. A + symbol may be used to require a word \
+    e.g: 'sensor +print' would require results to have 'print' in the searched categories.
+inventoryItem.search.text.found=Results for: {0}
+inventoryItem.search.text.none.found=No results for: {0}
+inventoryItem.search.text.below.reorder=Below Reorder
+inventoryItem.search.text.below.reorder.description=Inventory items at or below reorder point.
+inventoryItem.search.text.below.reorder.all=Below Reorder (all)
+inventoryItem.search.text.below.reorder.all.description=Inventory items at or below reorder point, including reorder listing disabled.
+inventoryItem.search.text.below.reorder.none.found=No inventory items found at or below reorder point.
+inventoryItem.search.text.all.description=All inventory items.
+inventoryItem.search.text.all.none.found=No inventory items found.
+inventoryItem.search.text.recently.used=Recently Used
+inventoryItem.search.text.recently.used.description=Items used in the last {0} days.
+inventoryItem.search.text.recently.used.none.found=No items used in the last {0} days.
+
+#
+# Report error messages.
+#
+
+report.error.too.many.results=Error: over {0} results, please run report again.
+report.error.no.locations.found=Error: no locations found, please run report again.
+report.error.too.many.locations=Error: over {0} locations, please run report again.
+report.error.no.inventory.items.found=Error: no inventory items found, please run report again.
+report.error.too.many.inventory.items=Error: over {0} inventory items, please run report again.
+report.error.multiple.currency.found=Error: multiple currency found.
+
+#
+# AppCore messages.
+#
+appCore.rebuild.text.search.index=The text search index is being rebuilt in the background, see log file for details.
Index: branches/features/taskProcedureRework/grails-app/i18n/messages_de.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages_de.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages_de.properties	(revision 753)
@@ -0,0 +1,30 @@
+default.doesnt.match.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] entspricht nicht dem vorgegebenen Muster [{3}]
+default.invalid.url.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gÃŒltige URL
+default.invalid.creditCard.message=Das Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gÃŒltige Kreditkartennummer
+default.invalid.email.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist keine gÃŒltige E-Mail Adresse
+default.invalid.range.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht im Wertebereich von [{3}] bis [{4}]
+default.invalid.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht im Wertebereich von [{3}] bis [{4}]
+default.invalid.max.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist grÃ¶Ãer als der HÃ¶chstwert von [{3}]
+default.invalid.min.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist kleiner als der Mindestwert von [{3}]
+default.invalid.max.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ÃŒbersteigt den HÃ¶chstwert von [{3}]
+default.invalid.min.size.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] unterschreitet den Mindestwert von [{3}]
+default.invalid.validator.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist ungÃŒltig
+default.not.inlist.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] ist nicht in der Liste [{3}] enthalten.
+default.blank.message=Die Eigenschaft [{0}] des Typs [{1}] darf nicht leer sein
+default.not.equal.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] darf nicht gleich [{3}] sein
+default.null.message=Die Eigenschaft [{0}] des Typs [{1}] darf nicht null sein
+default.not.unique.message=Die Eigenschaft [{0}] des Typs [{1}] mit dem Wert [{2}] darf nur einmal vorkommen
+
+default.paginate.prev=Vorherige
+default.paginate.next=NÃ€chste
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Die Eigenschaft {0} muss eine gÃŒltige URL sein
+typeMismatch.java.net.URI=Die Eigenschaft {0} muss eine gÃŒltige URI sein
+typeMismatch.java.util.Date=Die Eigenschaft {0} muss ein gÃŒltiges Datum sein
+typeMismatch.java.lang.Double=Die Eigenschaft {0} muss eine gÃŒltige Zahl sein
+typeMismatch.java.lang.Integer=Die Eigenschaft {0} muss eine gÃŒltige Zahl sein
+typeMismatch.java.lang.Long=Die Eigenschaft {0} muss eine gÃŒltige Zahl sein
+typeMismatch.java.lang.Short=Die Eigenschaft {0} muss eine gÃŒltige Zahl sein
+typeMismatch.java.math.BigDecimal=Die Eigenschaft {0} muss eine gÃŒltige Zahl sein
+typeMismatch.java.math.BigInteger=Die Eigenschaft {0} muss eine gÃŒltige Zahl sein
Index: branches/features/taskProcedureRework/grails-app/i18n/messages_es.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages_es.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages_es.properties	(revision 753)
@@ -0,0 +1,30 @@
+default.doesnt.match.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no corresponde al patrÃ³n [{3}]
+default.invalid.url.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no es una URL vÃ¡lida
+default.invalid.creditCard.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no es un nÃºmero de tarjeta de crÃ©dito vÃ¡lida
+default.invalid.email.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no es una direcciÃ³n de correo electrÃ³nico vÃ¡lida
+default.invalid.range.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no entra en el rango vÃ¡lido de [{3}] a [{4}]
+default.invalid.size.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no entra en el tamaÃ±o vÃ¡lido de [{3}] a [{4}]
+default.invalid.max.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] excede el valor mÃ¡ximo [{3}]
+default.invalid.min.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] es menos que el valor mÃ­nimo [{3}]
+default.invalid.max.size.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] excede el tamaÃ±o mÃ¡ximo de [{3}]
+default.invalid.min.size.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] es menor que el tamaÃ±o mÃ­nimo de [{3}]
+default.invalid.validator.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no es vÃ¡lido
+default.not.inlist.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no esta contenido dentro de la lista [{3}]
+default.blank.message=La propiedad [{0}] de la clase [{1}] no puede ser vacÃ­a
+default.not.equal.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] no puede igualar a [{3}]
+default.null.message=La propiedad [{0}] de la clase [{1}] no puede ser nulo
+default.not.unique.message=La propiedad [{0}] de la clase [{1}] con valor [{2}] debe ser Ãºnica
+
+default.paginate.prev=Anterior
+default.paginate.next=Siguiente
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=La propiedad {0} debe ser una URL vÃ¡lida
+typeMismatch.java.net.URI=La propiedad {0} debe ser una URI vÃ¡lida
+typeMismatch.java.util.Date=La propiedad {0} debe ser una fecha vÃ¡lida
+typeMismatch.java.lang.Double=La propiedad {0} debe ser un nÃºmero vÃ¡lido
+typeMismatch.java.lang.Integer=La propiedad {0} debe ser un nÃºmero vÃ¡lido
+typeMismatch.java.lang.Long=La propiedad {0} debe ser un nÃºmero vÃ¡lido
+typeMismatch.java.lang.Short=La propiedad {0} debe ser un nÃºmero vÃ¡lido
+typeMismatch.java.math.BigDecimal=La propiedad {0} debe ser un nÃºmero vÃ¡lido
+typeMismatch.java.math.BigInteger=La propiedad {0} debe ser un nÃºmero vÃ¡lido
Index: branches/features/taskProcedureRework/grails-app/i18n/messages_fr.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages_fr.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages_fr.properties	(revision 753)
@@ -0,0 +1,19 @@
+default.doesnt.match.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] ne correspond pas au pattern [{3}]
+default.invalid.url.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas une URL valide
+default.invalid.creditCard.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas un numÃ©ro de carte de crÃ©dit valide
+default.invalid.email.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas une adresse e-mail valide
+default.invalid.range.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas contenue dans l'intervalle [{3}] Ã  [{4}]
+default.invalid.size.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas contenue dans l'intervalle [{3}] Ã  [{4}]
+default.invalid.max.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] est supÃ©rieure Ã  la valeur maximum [{3}]
+default.invalid.min.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] est infÃ©rieure Ã  la valeur minimum [{3}]
+default.invalid.max.size.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] est supÃ©rieure Ã  la valeur maximum [{3}]
+default.invalid.min.size.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] est infÃ©rieure Ã  la valeur minimum [{3}]
+default.invalid.validator.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] n'est pas valide
+default.not.inlist.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] ne fait pas partie de la liste [{3}]
+default.blank.message=La propriÃ©tÃ© [{0}] de la classe [{1}] ne peut pas Ãªtre vide
+default.not.equal.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] ne peut pas Ãªtre Ã©gale Ã  [{3}]
+default.null.message=La propriÃ©tÃ© [{0}] de la classe [{1}] ne peut pas Ãªtre nulle
+default.not.unique.message=La propriÃ©tÃ© [{0}] de la classe [{1}] avec la valeur [{2}] doit Ãªtre unique
+
+default.paginate.prev=PrÃ©cÃ©dent
+default.paginate.next=Suivant
Index: branches/features/taskProcedureRework/grails-app/i18n/messages_it.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages_it.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages_it.properties	(revision 753)
@@ -0,0 +1,19 @@
+default.doesnt.match.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] non corrisponde al pattern [{3}]
+default.invalid.url.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] non Ãš un URL valido
+default.invalid.creditCard.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] non Ãš un numero di carta di credito valido
+default.invalid.email.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] non Ãš un indirizzo email valido
+default.invalid.range.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] non rientra nell'intervallo valido da [{3}] a [{4}]
+default.invalid.size.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] non rientra nell'intervallo di dimensioni valide da [{3}] a [{4}]
+default.invalid.max.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] Ãš maggiore di [{3}]
+default.invalid.min.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] Ãš minore di [{3}]
+default.invalid.max.size.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] Ãš maggiore di [{3}]
+default.invalid.min.size.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] Ãš minore di [{3}]
+default.invalid.validator.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] non Ãš valida
+default.not.inlist.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] non Ãš contenuta nella lista [{3}]
+default.blank.message=La proprietÃ  [{0}] della classe [{1}] non puÃ² essere vuota
+default.not.equal.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] non puÃ² essere uguale a [{3}]
+default.null.message=La proprietÃ  [{0}] della classe [{1}] non puÃ² essere null
+default.not.unique.message=La proprietÃ  [{0}] della classe [{1}] con valore [{2}] deve essere unica
+
+default.paginate.prev=Precedente
+default.paginate.next=Successivo
Index: branches/features/taskProcedureRework/grails-app/i18n/messages_ja.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages_ja.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages_ja.properties	(revision 753)
@@ -0,0 +1,22 @@
+default.doesnt.match.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ã[{3}]ãã¿ãŒã³ãšäžèŽããŠããŸããã
+default.invalid.url.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ãURLã§ã¯ãããŸããã
+default.invalid.creditCard.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ãæ­£åœãªã¯ã¬ãžããã«ãŒãçªå·ã§ã¯ãããŸããã
+default.invalid.email.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ãã¡ãŒã«ã¢ãã¬ã¹ã§ã¯ãããŸããã
+default.invalid.range.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ã[{3}]ãã[{4}]ç¯å²å
+ãæå®ããŠãã ããã
+default.invalid.size.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ã[{3}]ãã[{4}]ä»¥å
+ãæå®ããŠãã ããã
+default.invalid.max.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ãæå€§å€[{3}]ããå€§ããã§ãã
+default.invalid.min.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ãæå°å€[{3}]ããå°ããã§ãã
+default.invalid.max.size.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ãæå€§å€[{3}]ããå€§ããã§ãã
+default.invalid.min.size.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ãæå°å€[{3}]ããå°ããã§ãã
+default.invalid.validator.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ãã«ã¹ã¿ã ããªããŒã·ã§ã³ãééã§ããŸããã
+default.not.inlist.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ã[{3}]ãªã¹ãå
+ã«å­åšããŸããã
+default.blank.message=[{1}]ã¯ã©ã¹ã®ãã­ããã£[{0}]ã®ç©ºçœã¯èš±å¯ãããŸããã
+default.not.equal.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯ã[{3}]ãšåç­ã§ã¯ãããŸããã
+default.null.message=[{1}]ã¯ã©ã¹ã®ãã­ããã£[{0}]ã«nullã¯èš±å¯ãããŸããã
+default.not.unique.message=ã¯ã©ã¹[{1}]ãã­ããã£[{0}]ã®å€[{2}]ã¯æ¢ã«äœ¿çšãããŠããŸãã
+
+default.paginate.prev=æ»ã
+default.paginate.next=æ¬¡ãž
Index: branches/features/taskProcedureRework/grails-app/i18n/messages_nl.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages_nl.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages_nl.properties	(revision 753)
@@ -0,0 +1,30 @@
+default.doesnt.match.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] komt niet overeen met het vereiste patroon [{3}]
+default.invalid.url.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is geen geldige URL
+default.invalid.creditCard.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is geen geldig credit card nummer
+default.invalid.email.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is geen geldig e-mailadres
+default.invalid.range.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] valt niet in de geldige waardenreeks van [{3}] tot [{4}]
+default.invalid.size.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] valt niet in de geldige grootte van [{3}] tot [{4}]
+default.invalid.max.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] overschrijdt de maximumwaarde [{3}]
+default.invalid.min.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is minder dan de minimumwaarde [{3}]
+default.invalid.max.size.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] overschrijdt de maximumgrootte van [{3}]
+default.invalid.min.size.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is minder dan mainimumgrootte van [{3}]
+default.invalid.validator.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] is niet geldig
+default.not.inlist.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] komt niet voor in de lijst [{3}]
+default.blank.message=Attribuut [{0}] van entiteit [{1}] mag niet leeg zijn
+default.not.equal.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] mag niet gelijk zijn aan [{3}]
+default.null.message=Attribuut [{0}] van entiteit [{1}] mag niet leeg zijn
+default.not.unique.message=Attribuut [{0}] van entiteit [{1}] met waarde [{2}] moet uniek zijn
+
+default.paginate.prev=Vorige
+default.paginate.next=Volgende
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=Attribuut {0} is geen geldige URL
+typeMismatch.java.net.URI=Attribuut {0} is geen geldige URI
+typeMismatch.java.util.Date=Attribuut {0} is geen geldige datum
+typeMismatch.java.lang.Double=Attribuut {0} is geen geldig nummer
+typeMismatch.java.lang.Integer=Attribuut {0} is geen geldig nummer
+typeMismatch.java.lang.Long=Attribuut {0} is geen geldig nummer
+typeMismatch.java.lang.Short=Attribuut {0} is geen geldig nummer
+typeMismatch.java.math.BigDecimal=Attribuut {0} is geen geldig nummer
+typeMismatch.java.math.BigInteger=Attribuut {0} is geen geldig nummer
Index: branches/features/taskProcedureRework/grails-app/i18n/messages_pt_BR.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages_pt_BR.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages_pt_BR.properties	(revision 753)
@@ -0,0 +1,34 @@
+#
+# Translated by Lucas Teixeira - lucastex@gmail.com
+#
+
+default.doesnt.match.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o atende ao padrÃ£o definido [{3}]
+default.invalid.url.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o Ã© uma URL vÃ¡lida
+default.invalid.creditCard.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o Ã© um nÃºmero vÃ¡lido de cartÃ£o de crÃ©dito
+default.invalid.email.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o Ã© um endereÃ§o de email vÃ¡lido.
+default.invalid.range.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o estÃ¡ entre a faixa de valores vÃ¡lida de [{3}] atÃ© [{4}]
+default.invalid.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o estÃ¡ na faixa de tamanho vÃ¡lida de [{3}] atÃ© [{4}]
+default.invalid.max.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapass o valor mÃ¡ximo [{3}]
+default.invalid.min.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o atinge o valor mÃ­nimo [{3}]
+default.invalid.max.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] ultrapassa o tamanho mÃ¡ximo de [{3}]
+default.invalid.min.size.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o atinge o tamanho mÃ­nimo de [{3}]
+default.invalid.validator.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o passou na validaÃ§Ã£o
+default.not.inlist.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o Ã© um valor dentre os permitidos na lista [{3}]
+default.blank.message=O campo [{0}] da classe [{1}] nÃ£o pode ficar em branco
+default.not.equal.message=O campo [{0}] da classe [{1}] com o valor [{2}] nÃ£o pode ser igual a [{3}]
+default.null.message=O campo [{0}] da classe [{1}] nÃ£o pode ser vazia
+default.not.unique.message=O campo [{0}] da classe [{1}] com o valor [{2}] deve ser Ãºnico
+
+default.paginate.prev=Anterior
+default.paginate.next=PrÃ³ximo
+
+# Mensagens de erro em atribuiÃ§Ã£o de valores. Use "typeMismatch.$className.$propertyName" para customizar (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=O campo {0} deve ser uma URL vÃ¡lida.
+typeMismatch.java.net.URI=O campo {0} deve ser uma URI vÃ¡lida.
+typeMismatch.java.util.Date=O campo {0} deve ser uma data vÃ¡lida
+typeMismatch.java.lang.Double=O campo {0} deve ser um nÃºmero vÃ¡lido.
+typeMismatch.java.lang.Integer=O campo {0} deve ser um nÃºmero vÃ¡lido.
+typeMismatch.java.lang.Long=O campo {0} deve ser um nÃºmero vÃ¡lido.
+typeMismatch.java.lang.Short=O campo {0} deve ser um nÃºmero vÃ¡lido.
+typeMismatch.java.math.BigDecimal=O campo {0} deve ser um nÃºmero vÃ¡lido.
+typeMismatch.java.math.BigInteger=O campo {0} deve ser um nÃºmero vÃ¡lido.
Index: branches/features/taskProcedureRework/grails-app/i18n/messages_ru.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages_ru.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages_ru.properties	(revision 753)
@@ -0,0 +1,33 @@
+default.doesnt.match.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐœÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ ÐŸÐ±ÑÐ°Ð·ÑÑ [{3}]
+default.invalid.url.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ URL-Ð°ÐŽÑÐµÑÐŸÐŒ
+default.invalid.creditCard.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ ÐœÐŸÐŒÐµÑÐŸÐŒ ÐºÑÐµÐŽÐžÑÐœÐŸÐ¹ ÐºÐ°ÑÑÑ
+default.invalid.email.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ e-mail Ð°ÐŽÑÐµÑÐŸÐŒ
+default.invalid.range.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐœÐµ Ð¿ÐŸÐ¿Ð°ÐŽÐ°ÐµÑ Ð² ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐ¹ ÐžÐœÑÐµÑÐ²Ð°Ð» ÐŸÑ [{3}] ÐŽÐŸ [{4}]
+default.invalid.size.message=Ð Ð°Ð·ÐŒÐµÑ Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] (Ð·ÐœÐ°ÑÐµÐœÐžÐµ: [{2}]) ÐœÐµ Ð¿ÐŸÐ¿Ð°ÐŽÐ°ÐµÑ Ð² ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐ¹ ÐžÐœÑÐµÑÐ²Ð°Ð» ÐŸÑ [{3}] ÐŽÐŸ [{4}]
+default.invalid.max.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] Ð±ÐŸÐ»ÑÑÐµ ÑÐµÐŒ ÐŒÐ°ÐºÑÐžÐŒÐ°Ð»ÑÐœÐŸ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ [{3}]
+default.invalid.min.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐŒÐµÐœÑÑÐµ ÑÐµÐŒ ÐŒÐžÐœÐžÐŒÐ°Ð»ÑÐœÐŸ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ [{3}]
+default.invalid.max.size.message=Ð Ð°Ð·ÐŒÐµÑ Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] (Ð·ÐœÐ°ÑÐµÐœÐžÐµ: [{2}]) Ð±ÐŸÐ»ÑÑÐµ ÑÐµÐŒ ÐŒÐ°ÐºÑÐžÐŒÐ°Ð»ÑÐœÐŸ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐ¹ ÑÐ°Ð·ÐŒÐµÑ [{3}]
+default.invalid.min.size.message=Ð Ð°Ð·ÐŒÐµÑ Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] (Ð·ÐœÐ°ÑÐµÐœÐžÐµ: [{2}]) ÐŒÐµÐœÑÑÐµ ÑÐµÐŒ ÐŒÐžÐœÐžÐŒÐ°Ð»ÑÐœÐŸ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐ¹ ÑÐ°Ð·ÐŒÐµÑ [{3}]
+default.invalid.validator.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐœÐµ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÐŸ
+default.not.inlist.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐœÐµ Ð¿ÐŸÐ¿Ð°ÐŽÐ°ÐµÑ Ð² ÑÐ¿ÐžÑÐŸÐº ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ [{3}]
+default.blank.message=ÐÐŸÐ»Ðµ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿ÑÑÑÑÐŒ
+default.not.equal.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÑÐ°Ð²ÐœÐŸ [{3}]
+default.null.message=ÐÐŸÐ»Ðµ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐœÐµ ÐŒÐŸÐ¶ÐµÑ ÐžÐŒÐµÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ null
+default.not.unique.message=ÐÐœÐ°ÑÐµÐœÐžÐµ [{2}] Ð¿ÐŸÐ»Ñ [{0}] ÐºÐ»Ð°ÑÑÐ° [{1}] ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð±ÑÑÑ ÑÐœÐžÐºÐ°Ð»ÑÐœÑÐŒ
+
+default.paginate.prev=ÐÑÐµÐŽÑÐŽÑÑÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ°
+default.paginate.next=Ð¡Ð»ÐµÐŽÑÑÑÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ°
+
+# ÐÑÐžÐ±ÐºÐž Ð¿ÑÐž Ð¿ÑÐžÑÐ²ÐŸÐµÐœÐžÐž ÐŽÐ°ÐœÐœÑÑ
+. ÐÐ»Ñ ÑÐŸÑÐœÐŸÐ¹ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐŽÐ»Ñ Ð¿ÐŸÐ»ÐµÐ¹ ÐºÐ»Ð°ÑÑÐŸÐ² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ
+# ÑÐŸÑÐŒÐ°Ñ "typeMismatch.$className.$propertyName" (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, typeMismatch.Book.author)
+typeMismatch.java.net.URL=ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸÐ»Ñ {0} ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ URL
+typeMismatch.java.net.URI=ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸÐ»Ñ {0} ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ URI
+typeMismatch.java.util.Date=ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸÐ»Ñ {0} ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÐŸÐ¹ ÐŽÐ°ÑÐŸÐ¹
+typeMismatch.java.lang.Double=ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸÐ»Ñ {0} ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ ÑÐžÑÐ»ÐŸÐŒ
+typeMismatch.java.lang.Integer=ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸÐ»Ñ {0} ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ ÑÐžÑÐ»ÐŸÐŒ
+typeMismatch.java.lang.Long=ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸÐ»Ñ {0} ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ ÑÐžÑÐ»ÐŸÐŒ
+typeMismatch.java.lang.Short=ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸÐ»Ñ {0} ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ ÑÐžÑÐ»ÐŸÐŒ
+typeMismatch.java.math.BigDecimal=ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸÐ»Ñ {0} ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ ÑÐžÑÐ»ÐŸÐŒ
+typeMismatch.java.math.BigInteger=ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸÐ»Ñ {0} ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ ÑÐžÑÐ»ÐŸÐŒ
Index: branches/features/taskProcedureRework/grails-app/i18n/messages_th.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages_th.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages_th.properties	(revision 753)
@@ -0,0 +1,30 @@
+default.doesnt.match.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] à¹àž¡à¹àžàž¹àžàžà¹àž­àžàžàž²àž¡àž£àž¹àžà¹àžàžàžàžµà¹àžàž³àž«àžàžà¹àž§à¹à¹àž [{3}]
+default.invalid.url.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] à¹àž¡à¹àžàž¹àžàžà¹àž­àžàžàž²àž¡àž£àž¹àžà¹àžàž URL
+default.invalid.creditCard.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] à¹àž¡à¹àžàž¹àžàžà¹àž­àžàžàž²àž¡àž£àž¹àžà¹àžàžàž«àž¡àž²àž¢à¹àž¥àžàžàž±àžàž£à¹àžàž£àžàžŽàž
+default.invalid.email.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] à¹àž¡à¹àžàž¹àžàžà¹àž­àžàžàž²àž¡àž£àž¹àžà¹àžàžàž­àžµà¹àž¡àž¥à¹
+default.invalid.range.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] à¹àž¡à¹à¹àžà¹àž¡àžµàžà¹àž²àžàžµà¹àžàž¹àžàžà¹àž­àžà¹àžàžà¹àž§àžàžàž²àž [{3}] àžàž¶àž [{4}]
+default.invalid.size.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] à¹àž¡à¹à¹àžà¹àž¡àžµàžàžàž²àžàžàžµà¹àžàž¹àžàžà¹àž­àžà¹àžàžà¹àž§àžàžàž²àž [{3}] àžàž¶àž [{4}]
+default.invalid.max.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] àž¡àžµàžà¹àž²à¹àžàžŽàžàžàž§à¹àž²àžà¹àž²àž¡àž²àžàžªàžžàž [{3}]
+default.invalid.min.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] àž¡àžµàžà¹àž²àžà¹àž­àž¢àžàž§à¹àž²àžà¹àž²àžà¹àž³àžªàžžàž  [{3}]
+default.invalid.max.size.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] àž¡àžµàžàžàž²àžà¹àžàžŽàžàžàž§à¹àž²àžàžàž²àžàž¡àž²àžàžªàžžàžàžàž­àž [{3}]
+default.invalid.min.size.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] àž¡àžµàžàžàž²àžàžà¹àž³àžàž§à¹àž²àžàžàž²àžàžà¹àž³àžªàžžàžàžàž­àž  [{3}]
+default.invalid.validator.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] à¹àž¡à¹àžà¹àž²àžàžàž²àž£àžàž§àžàžªàž­àžàžà¹àž²àžàžµà¹àžàž±à¹àžàžàž¶à¹àž
+default.not.inlist.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] à¹àž¡à¹à¹àžà¹àž­àž¢àž¹à¹à¹àžàž£àž²àž¢àžàž²àž£àžà¹àž­à¹àžàžàžµà¹  [{3}]
+default.blank.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] à¹àž¡à¹àžªàž²àž¡àž²àž£àžà¹àžà¹àžàžà¹àž²àž§à¹àž²àžà¹àžà¹
+default.not.equal.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] à¹àž¡à¹àžªàž²àž¡àž²àž£àžà¹àžà¹àž²àžàž±àž [{3}] à¹àžà¹
+default.null.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] à¹àž¡à¹àžªàž²àž¡àž²àž£àžà¹àžà¹àž null à¹àžà¹
+default.not.unique.message=àžàžžàžàžªàž¡àžàž±àžàžŽ [{0}] àžàž­àžàžàž¥àž²àžª [{1}] àžàž¶à¹àžàž¡àžµàžà¹àž²à¹àžà¹àž [{2}] àžàž°àžà¹àž­àžà¹àž¡à¹àžà¹àž³ (unique)
+
+default.paginate.prev=àžà¹àž­àžàž«àžà¹àž²
+default.paginate.next=àžàž±àžà¹àž
+
+# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
+typeMismatch.java.net.URL=àžàžžàžàžªàž¡àžàž±àžàžŽ '{0}' àžàž°àžà¹àž­àžà¹àžà¹àžàžà¹àž² URL àžàžµà¹àžàž¹àžàžà¹àž­àž
+typeMismatch.java.net.URI=àžàžžàžàžªàž¡àžàž±àžàžŽ '{0}' àžàž°àžà¹àž­àžà¹àžà¹àžàžà¹àž² URI àžàžµà¹àžàž¹àžàžà¹àž­àž
+typeMismatch.java.util.Date=àžàžžàžàžªàž¡àžàž±àžàžŽ '{0}' àžàž°àžà¹àž­àžàž¡àžµàžà¹àž²à¹àžà¹àžàž§àž±àžàžàžµà¹
+typeMismatch.java.lang.Double=àžàžžàžàžªàž¡àžàž±àžàžŽ '{0}' àžàž°àžà¹àž­àžàž¡àžµàžà¹àž²à¹àžà¹àžàžàž³àžàž§àžàžàž£àž°à¹àž àž Double
+typeMismatch.java.lang.Integer=àžàžžàžàžªàž¡àžàž±àžàžŽ '{0}' àžàž°àžà¹àž­àžàž¡àžµàžà¹àž²à¹àžà¹àžàžàž³àžàž§àžàžàž£àž°à¹àž àž Integer
+typeMismatch.java.lang.Long=àžàžžàžàžªàž¡àžàž±àžàžŽ '{0}' àžàž°àžà¹àž­àžàž¡àžµàžà¹àž²à¹àžà¹àžàžàž³àžàž§àžàžàž£àž°à¹àž àž Long
+typeMismatch.java.lang.Short=àžàžžàžàžªàž¡àžàž±àžàžŽ '{0}' àžàž°àžà¹àž­àžàž¡àžµàžà¹àž²à¹àžà¹àžàžàž³àžàž§àžàžàž£àž°à¹àž àž Short
+typeMismatch.java.math.BigDecimal=àžàžžàžàžªàž¡àžàž±àžàžŽ '{0}' àžàž°àžà¹àž­àžàž¡àžµàžà¹àž²à¹àžà¹àžàžàž³àžàž§àžàžàž£àž°à¹àž àž BigDecimal
+typeMismatch.java.math.BigInteger=àžàžžàžàžªàž¡àžàž±àžàžŽ '{0}' àžàž°àžà¹àž­àžàž¡àžµàžà¹àž²à¹àžà¹àžàžàž³àžàž§àžàžàž£àž°à¹àž àž BigInteger
Index: branches/features/taskProcedureRework/grails-app/i18n/messages_zh_CN.properties
===================================================================
--- branches/features/taskProcedureRework/grails-app/i18n/messages_zh_CN.properties	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/i18n/messages_zh_CN.properties	(revision 753)
@@ -0,0 +1,18 @@
+default.blank.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u4E0D\u80FD\u4E3A\u7A7A
+default.doesnt.match.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0E\u5B9A\u4E49\u7684\u6A21\u5F0F [{3}]\u4E0D\u5339\u914D
+default.invalid.creditCard.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u4FE1\u7528\u5361\u53F7
+default.invalid.email.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u5408\u6CD5\u7684\u7535\u5B50\u90AE\u4EF6\u5730\u5740
+default.invalid.max.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u6BD4\u6700\u5927\u503C [{3}]\u8FD8\u5927
+default.invalid.max.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u6BD4\u6700\u5927\u503C [{3}]\u8FD8\u5927
+default.invalid.min.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u6BD4\u6700\u5C0F\u503C [{3}]\u8FD8\u5C0F
+default.invalid.min.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u6BD4\u6700\u5C0F\u503C [{3}]\u8FD8\u5C0F
+default.invalid.range.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u5728\u5408\u6CD5\u7684\u8303\u56F4\u5185( [{3}] \uFF5E [{4}] )
+default.invalid.size.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u7684\u5927\u5C0F\u4E0D\u5728\u5408\u6CD5\u7684\u8303\u56F4\u5185( [{3}] \uFF5E [{4}] )
+default.invalid.url.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u662F\u4E00\u4E2A\u5408\u6CD5\u7684URL
+default.invalid.validator.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u672A\u80FD\u901A\u8FC7\u81EA\u5B9A\u4E49\u7684\u9A8C\u8BC1
+default.not.equal.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0E[{3}]\u4E0D\u76F8\u7B49
+default.not.inlist.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u4E0D\u5728\u5217\u8868\u7684\u53D6\u503C\u8303\u56F4\u5185
+default.not.unique.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u7684\u503C[{2}]\u5FC5\u987B\u662F\u552F\u4E00\u7684
+default.null.message=[{1}]\u7C7B\u7684\u5C5E\u6027[{0}]\u4E0D\u80FD\u4E3Anull
+default.paginate.next=\u4E0B\u9875
+default.paginate.prev=\u4E0A\u9875
Index: branches/features/taskProcedureRework/grails-app/jobs/InventoryIndexJob.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/jobs/InventoryIndexJob.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/jobs/InventoryIndexJob.groovy	(revision 753)
@@ -0,0 +1,39 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
+/**
+* Provides a quartz job that rebuilds the searchable index for the inventory search.
+* With concurrent=false the next job is blocked until the previous job completes.
+* We need a hibernate session otherwise we get a LazyInitializationException, default is true but we specify it to be sure.
+* Rebuilding the index is required since searchable components are not updated when they change, that is
+* until the parent is updated and reindexed. Cascade update is broken in searchable-0.5.5
+*/
+class InventoryIndexJob {
+
+    def concurrent = false
+    def sessionRequired = true
+
+    static triggers = {
+        // Cron fields:
+        // 'Seconds Minutes Hours DOM Month DOW Year(Optional)'
+        // See: http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html
+        // Trigger every hour on the hour:
+        //cron name: 'RebuildInventoryIndex', cronExpression: "0 0 * * * ?"
+    }
+
+    def execute(context) {
+
+        // Some information can be accessed if we run with "def execute(context) ".
+        // For more info see: http://quartz.sourceforge.net/javadoc/org/quartz/JobExecutionContext.html
+        // log.debug context.getTrigger()
+        // log.debug context.getPreviousFireTime()
+        // log.debug context.getFireTime()
+
+        // Called by.
+        def calledBy =  context.mergedJobDataMap.get('calledBy')
+        log.info "Called By: " + calledBy
+
+        // Rebuild the Inventory searchable index.
+        log.info "Calling, Inventory.index()."
+        InventoryItem.index()
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/jobs/TaskRecurringScheduleJob.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/jobs/TaskRecurringScheduleJob.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/jobs/TaskRecurringScheduleJob.groovy	(revision 753)
@@ -0,0 +1,35 @@
+import org.codehaus.groovy.grails.commons.*
+
+/**
+* Provides a quartz job that reviews and generates all recurring tasks.
+* The quartz scheduler is restarted if this file is edited so startDelay will then delay again.
+* The execute method is called once every repeatInterval (in milliseconds).
+* With concurrent=false the next job is blocked until the previous job completes.
+* Apparently we need a hibernate session otherwise we get a LazyInitializationException, default is true but we specify it to be sure.
+*/
+class TaskRecurringScheduleJob {
+
+    def taskRecurringScheduleService
+
+    def concurrent = false
+    def sessionRequired = true
+
+    // The repeatInterval starts counting again after firing, but concurrent = false may block firing until the previous job completes.
+    static triggers = {
+        simple name: "GenerateAll",
+                    startDelay: 60000,
+                    repeatInterval: ConfigurationHolder.config.taskRecurringScheduleJob.repeatInterval*1000
+    }
+
+    def execute() {
+
+        // Some information can be accessed if we run with "def execute(context) ".
+        // For more info see: http://quartz.sourceforge.net/javadoc/org/quartz/JobExecutionContext.html
+        // log.debug context.getTrigger()
+        // log.debug context.getPreviousFireTime()
+        // log.debug context.getFireTime()
+
+        // We do everything via services, quartz just sets up and fires off the thread.
+        taskRecurringScheduleService.generateAll()
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/services/AddressService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/AddressService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/AddressService.groovy	(revision 753)
@@ -0,0 +1,70 @@
+/**
+ * Provides a service class with methods to interact with Address domain class.
+ * Address stores the address for various objects in the database.
+ */
+class AddressService {
+
+    boolean transactional = false
+
+    def getAddress() {
+        """${this.street1}
+        ${this.street2}
+        ${this.city}
+        ${this.state}
+        ${this.postCode}
+        ${this.country}"""
+
+    }
+
+    def create(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["Address", params.id] ]
+            return result
+        }
+
+        if(!checkForOwner(params))
+            return fail(code:"address.owner.not.found")
+
+        result.addressInstance = new Address()
+        result.addressInstance.properties = params
+
+        // success
+        return result
+    }
+
+    def save(params) {
+        def result = [:]
+        def fail = { Map m ->
+            if(result.addressInstance && m.field)
+                result.addressInstance.errors.rejectValue(m.field, m.code)
+            result.error = [ code: m.code, args: ["Address", params.id] ]
+            return result
+        }
+
+        if(!checkForOwner(params))
+            return fail(code:"address.owner.not.found")
+
+        result.addressInstance = new Address(params)
+
+        if(result.addressInstance.hasErrors() || !result.addressInstance.save(flush: true))
+            return fail(code:"default.create.failure")
+
+        // success
+        return result
+    }
+
+    private checkForOwner(params) {
+
+        if(params.supplier?.id)
+            return Supplier.exists(params.supplier.id)
+        if(params.person?.id)
+            return Person.exists(params.person.id)
+        if(params.site?.id)
+            return Site.exists(params.site.id)
+
+        return false
+    }
+
+
+} // end of class
Index: branches/features/taskProcedureRework/grails-app/services/AppConfigService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/AppConfigService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/AppConfigService.groovy	(revision 753)
@@ -0,0 +1,56 @@
+/**
+ * Provides a service class with methods to interact with AppConfig.
+ * AppConfig stores various application configuration (settings) in the database.
+ */
+class AppConfigService {
+
+    boolean transactional = false
+
+    /**
+    * Set the value of an appConfig.
+    * @param name The name of the appConfig.
+    * @param value Set to this value if specified else defaults to "true".
+    * @returns True if success otherwise false.
+    */
+    public Boolean set(String name, String value = "true") {
+        def appConfig = AppConfig.findByName(name)
+        appConfig ? (appConfig.value = value) : (appConfig = new AppConfig(name: name, value: value))
+        appConfig.save() ? true : false
+    }
+
+    /**
+    * Check if an appConfig exists.
+    * @param name The name of the appConfig.
+    * @returns True if success otherwise false.
+    */
+    public Boolean exists(String name) {
+        AppConfig.findByName(name) ? true : false
+    }
+
+    /**
+    * Get the value of an appConfig.
+    * @param name The name of the appConfig.
+    * @returns The value of the appConfig else false.
+    */
+    def getValue(String name) {
+        def appConfig = AppConfig.findByName(name)
+        appConfig ? appConfig.value : false
+    }
+
+    /**
+    * Delete an appConfig.
+    * @param name The name of the appConfig.
+    * @returns True if success otherwise false.
+    */
+    public Boolean delete(String name) {
+        try {
+            AppConfig.findByName(name).delete(flush:true)
+            return true
+        }
+        catch(e) {
+            log.debug("Could not delete, appConfig may not exist.")
+            return false
+        }
+    }
+
+} // end of class
Index: branches/features/taskProcedureRework/grails-app/services/AssetCsvService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/AssetCsvService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/AssetCsvService.groovy	(revision 753)
@@ -0,0 +1,471 @@
+import grails.util.GrailsUtil
+import au.com.bytecode.opencsv.CSVWriter
+import au.com.bytecode.opencsv.CSVReader
+import org.apache.commons.lang.WordUtils
+
+/**
+ * Provides some csv import/export methods.
+ * Requires the opencsv jar to be available which is included in the grails-export plugin.
+ */
+class AssetCsvService {
+
+    boolean transactional = false
+
+    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
+
+    def sessionFactory
+    def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP
+
+    /**
+    * Import an asset tree creating items as required.
+    * @param request The http request to run getFile against.
+    * Get file should return a csv format file containing the asset tree as per template.
+    */
+    def importAssetTree(request) {
+        Asset.withTransaction { status ->
+            def result = [:]
+
+            def kByteMultiplier = 1000
+            def fileMaxSize = 500 * kByteMultiplier
+            def logFileLink = g.link(controller: "appCore", action: "appLog") {"log"}
+
+            def multiPartFile = request.getFile('file')
+
+            InputStreamReader sr = new InputStreamReader(multiPartFile.inputStream)
+            CSVReader reader = new CSVReader(sr)
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                reader.close()
+                result.error = [ code: m.code, args: m.args ]
+                return result
+            }
+
+            if(!multiPartFile || multiPartFile.isEmpty())
+                return fail(code: "default.file.not.supplied")
+
+            if (multiPartFile.getSize() > fileMaxSize)
+                return fail(code: "default.file.over.max.size", args: [fileMaxSize/kByteMultiplier, "kB"])
+
+            def columnIndex = 0
+            def nameColumnIndex = 0
+            def numberOfColumns = 0
+            def maxNumberOfColumns = 20
+
+            // Get first line.
+            def line = reader.readNext()
+            def lineNumber = 1
+
+            // Check for header line 1.
+            if(line != templateHeaderLine1) {
+                log.error "Failed to find header line 1. "
+                log.error "Required: " + templateHeaderLine1.toString()
+                log.error "Supplied: " + line.toString()
+                return fail(code: "default.file.no.header")
+            }
+
+            // Get second line.
+            line = reader.readNext()
+            lineNumber ++
+
+            // Check for header line 2.
+            if(line != templateHeaderLine2) {
+                log.error "Failed to find header line 2. "
+                log.error "Required: " + templateHeaderLine2.toString()
+                log.error "Supplied: " + line.toString()
+                return fail(code: "default.file.no.header")
+            }
+
+            log.info "Import checks passed, start processing asset file."
+
+            // Prepare the first body line.
+            line = reader.readNext()
+            lineNumber ++
+
+            def siteInstance
+            def departmentInstance
+            def sectionInstance
+            def assetInstance
+            def assetSubItemInstance
+            def parentItem
+
+            def column = [:]
+
+            def nextLine = {
+                    line = reader.readNext()
+                    lineNumber ++
+                    log.info "Processing line: " + lineNumber
+            }
+
+            def nextColumn = {
+                nameColumnIndex = columnIndex
+
+                if( (columnIndex+1) < numberOfColumns ) {
+                    // Capitalise and assign the name and description columns.
+                    use(WordUtils) {
+                    column.name = line[columnIndex].trim().capitalize()
+                    column.description = line[++columnIndex].trim().capitalize()
+                    }
+                }
+                else if( columnIndex < numberOfColumns ) {
+                    // Capitalise and assign the name column with a blank description.
+                    use(WordUtils) {
+                    column.name = line[columnIndex].trim().capitalize()
+                    column.description = ''
+                    }
+                }
+                else {
+                    log.info "No more columns on line: " + lineNumber
+                    return false
+                }
+
+                if(!column.name) {
+                    log.info "No name at " + "line: " + lineNumber + " col: " + nameColumnIndex
+                    return false
+                }
+
+                columnIndex++
+                // Success.
+                return column
+            }
+
+            // Primary loop.
+            while(line) {
+                numberOfColumns = Math.min( line.size(), maxNumberOfColumns )
+                columnIndex = 0
+
+                if(!nextColumn()) {
+                    nextLine()
+                    continue
+                }
+
+                // Ignore comment lines.
+                if(line.toString().toLowerCase().contains("comment")) {
+                    log.info "Comment line found."
+                    nextLine()
+                    continue
+                }
+
+                // Ignore example lines.
+                if(line.toString().toLowerCase().contains("example")) {
+                    log.info "Example line found."
+                    nextLine()
+                    continue
+                }
+
+                // Site.
+                siteInstance = Site.findByName(column.name)
+                if(!siteInstance) {
+                    log.info "Creating site: " + column.name
+                    siteInstance = new Site(name: column.name,
+                                                                description: column.description)
+                    if(!siteInstance.save()) {
+                        log.error "Failed to create site on line: " + column.name + "(" + lineNumber + ")"
+                        return fail(code: "asset.tree.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+                else log.info "Existing site: " + siteInstance
+
+                if(!nextColumn()) {
+                    nextLine()
+                    continue
+                }
+
+                // Department.
+                departmentInstance = Department.findByName(column.name)
+                if(!departmentInstance) {
+                    log.info "Creating department: " + column.name
+                    departmentInstance = new Department(name: column.name,
+                                                                                            description: column.description,
+                                                                                            site: siteInstance)
+                    if(!departmentInstance.save()) {
+                        log.error "Failed to create department on line: " + column.name + "(" + lineNumber + ")"
+                        return fail(code: "asset.tree.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+                else log.info "Existing department: " + departmentInstance
+
+                if(!nextColumn()) {
+                    nextLine()
+                    continue
+                }
+
+                // Section.
+                sectionInstance = Section.findByName(column.name)
+                if(!sectionInstance) {
+                    log.info "Creating section: " + column.name
+                    sectionInstance =  new Section(name: column.name,
+                                                                            description: column.description,
+                                                                            site: siteInstance,
+                                                                            department: departmentInstance)
+                    if(!sectionInstance.save()) {
+                        log.error "Failed to create section on line: " + column.name + "(" + lineNumber + ")"
+                        return fail(code: "asset.tree.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+                else log.info "Existing section: " + sectionInstance
+
+                if(!nextColumn()) {
+                    nextLine()
+                    continue
+                }
+
+                // Asset.
+                assetInstance = Asset.findByName(column.name)
+                if(!assetInstance) {
+                    log.info "Creating asset: " + column.name
+                    assetInstance = new Asset(name: column.name,
+                                                                    description: column.description,
+                                                                    section: sectionInstance)
+                    if(!assetInstance.save()) {
+                        log.error "Failed to create asset on line: " + column.name + "(" + lineNumber + ")"
+                        return fail(code: "asset.tree.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+                else log.info "Existing asset: " + assetInstance
+
+                if(!nextColumn()) {
+                    nextLine()
+                    continue
+                }
+
+                // AssetSubItem Level 1.
+                assetSubItemInstance = AssetSubItem.findByName(column.name)
+                if(!assetSubItemInstance) {
+                    log.info "Creating asset sub item: " + column.name
+                    assetSubItemInstance = new AssetSubItem(name: column.name,
+                                                                                                description: column.description)
+                    if(!assetInstance.save()) {
+                        log.error "Failed to create assetSubItem on line: " + column.name + "(" + lineNumber + ")"
+                        return fail(code: "asset.tree.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+                else log.info "Existing asset sub item: " + assetSubItemInstance
+
+                assetInstance.addToAssetSubItems(assetSubItemInstance)
+
+                // Remaining AssetSubItems.
+                while( nextColumn() ) {
+
+                    parentItem = assetSubItemInstance
+                    assetSubItemInstance = AssetSubItem.findByName(column.name)
+                    if(!assetSubItemInstance) {
+                        log.info "Creating asset sub item: " + column.name
+                        assetSubItemInstance = new AssetSubItem(name: column.name,
+                                                                                                    description: column.description,
+                                                                                                    parentItem: parentItem)
+                        if(!assetSubItemInstance.save()) {
+                            log.error "Failed to create assetSubItem on line: " + column.name + "(" + lineNumber + ")"
+                            return fail(code: "asset.tree.import.failure", args: [lineNumber, logFileLink])
+                        }
+                    }
+                    else log.info "Existing asset sub item: " + assetSubItemInstance
+
+                } // while( nextColumn() )
+
+                if(lineNumber % 100 == 0)
+                    cleanUpGorm()
+
+                nextLine()
+            } //while(line)
+
+            // Success.
+            log.info "End of file."
+            reader.close()
+            return result
+
+        } //end withTransaction
+    } // end importAssetTree()
+
+    /**
+    * Build an asset tree template csv file.
+    * This template can then be populated for import.
+    * @returns The template as a String in csv format.
+    */
+    def buildAssetTreeTemplate() {
+
+        StringWriter sw = new StringWriter()
+        CSVWriter writer = new CSVWriter(sw)
+
+        writeTemplateLines(writer)
+
+        writer.close()
+        return sw.toString()
+    }
+
+    private writeTemplateLines(writer) {
+        writer.writeNext(templateHeaderLine1 as String[])
+        writer.writeNext(templateHeaderLine2 as String[])
+        writer.writeNext()
+        writer.writeNext(["Example: Site1", "", "Department 1", "", "Section 1", "", "Asset 1", ""] as String[])
+        writer.writeNext()
+        writer.writeNext(["Example: Site1", "", "Department 1", "", "Section 1", "", "Asset 2", ""] as String[])
+        writer.writeNext()
+        writer.writeNext("Comment: The first two header lines are required.")
+        writer.writeNext("Comment: Leave a blank line between assets.")
+        writer.writeNext("Comment: Names are required, descriptions are optional.")
+        writer.writeNext("Comment: Identical and existing names will be considered as the same item.")
+        writer.writeNext("Comment: An asset may share the first level of asset sub items with other assets.")
+        writer.writeNext("Comment: Lower levels of asset sub items are only parented once but may have many children.")
+        writer.writeNext("Comment: Lines containing 'comment' will be ignored.")
+        writer.writeNext("Comment: Lines containing 'example' will be ignored.")
+        writer.writeNext("Comment: This file must be saved as a CSV file before import.")
+        writer.writeNext()
+    }
+
+    /**
+    * Build an asset tree test file.
+    * This test file can be imported to test the import and template methods.
+    * @returns The test file as a String in csv format.
+    */
+    def buildAssetTreeTest() {
+
+        StringWriter sw = new StringWriter()
+        CSVWriter writer = new CSVWriter(sw)
+
+        writeTemplateLines(writer)
+
+        writer.writeNext(["Lake Press", "Lake Press Site",
+                                        "Print Department", "The printing department",
+                                        "Press Section", "Contains all printing units",
+                                        "Print Unit 1", "Printing Unit Number 1",
+                                        "Print Unit", "Print Unit (Common to all units)",
+                                        "Print Couple", "Includes  blanket cylinder",
+                                        "Motor", "Main Drive Motor",
+                                        "NDS Bearing", "Non Drive Side Main Bearing"
+                                        ] as String[])
+
+        writer.writeNext(["Lake Press", "Lake Press Site",
+                                        "Print Department", "The printing department",
+                                        "Press Section", "Contains all printing units",
+                                        "Print Unit 1", "Printing Unit Number 1",
+                                        "Print Unit", "Print Unit (Common to all units)",
+                                        "Print Couple", "Includes  blanket cylinder",
+                                        "Motor", "Main Drive Motor",
+                                        "DS Bearing", "Drive Side Main Bearing"
+                                        ] as String[])
+
+        writer.close()
+        return sw.toString()
+    }
+
+    /**
+    * Build complete asset trees for export.
+    * @param assetList The list of assets to build and export trees for.
+    * @returns The tree as a String in csv format.
+    */
+    def buildAssetTree(List assetList) {
+
+        StringWriter sw = new StringWriter()
+        CSVWriter writer = new CSVWriter(sw)
+
+        writeTemplateLines(writer)
+
+        //Rows
+        def row
+
+        def writeAssetSubItem4 = { assetSubItem ->
+            row.add(assetSubItem.name)
+            row.add(assetSubItem.description)
+            writer.writeNext(row as String[])
+        }
+
+        def writeAssetSubItem3 = { assetSubItem ->
+            row.add(assetSubItem.name)
+            row.add(assetSubItem.description)
+
+            if(assetSubItem.subItems.size() > 0) {
+                assetSubItem.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }.each() { assetSubItem4 ->
+                    writeAssetSubItem4(assetSubItem4)
+                    row.removeRange(row.size()-2, row.size())
+                }
+            }
+            else {
+                writer.writeNext(row as String[])
+            }
+
+        }
+
+        def writeAssetSubItem2 = { assetSubItem ->
+            row.add(assetSubItem.name)
+            row.add(assetSubItem.description)
+
+            if(assetSubItem.subItems.size() > 0) {
+                assetSubItem.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }.each() { assetSubItem3 ->
+                    writeAssetSubItem3(assetSubItem3)
+                    row.removeRange(row.size()-2, row.size())
+                }
+            }
+            else {
+                writer.writeNext(row as String[])
+            }
+
+        }
+
+        def writeAssetSubItem1 = { assetSubItem ->
+            row.add(assetSubItem.name)
+            row.add(assetSubItem.description)
+
+            if(assetSubItem.subItems.size() > 0) {
+                assetSubItem.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }.each() { assetSubItem2 ->
+                    writeAssetSubItem2(assetSubItem2)
+                    row.removeRange(row.size()-2, row.size())
+                }
+            }
+            else {
+                writer.writeNext(row as String[])
+            }
+
+        }
+
+        assetList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }.each() { asset ->
+            row = []
+            writer.writeNext(row as String[]) //blank row between assets.
+            row.add(asset.section.site.name)
+            row.add(asset.section.site.description)
+            row.add(asset.section.department.name)
+            row.add(asset.section.department.description)
+            row.add(asset.section.name)
+            row.add(asset.section.description)
+            row.add(asset.name)
+            row.add(asset.description)
+
+            if(asset.assetSubItems.size() > 0) {
+                asset.assetSubItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }.each() { assetSubItem1 ->
+                    writeAssetSubItem1(assetSubItem1)
+                    row.removeRange(row.size()-2, row.size())
+                }
+            }
+            else {
+                writer.writeNext(row as String[])
+            }
+
+        }
+
+        writer.close()
+        return sw.toString()
+    } // end buildAssetTree
+
+    private getTemplateHeaderLine1() {
+            ["Site", "", "Department", "", "Section", "","Asset", "", "Sub Asset", "", "Functional Assembly", "", "Sub Assembly Group", "", "SubItem", ""]
+    }
+
+    private getTemplateHeaderLine2() {
+            (["Name", "Description"])*8
+    }
+
+    /**
+    * This cleans up the hibernate session and a grails map.
+    * For more info see: http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/
+    * The hibernate session flush is normal for hibernate.
+    * The map is apparently used by grails for domain object validation errors.
+    * A starting point for clean up is every 100 objects.
+    */
+    def cleanUpGorm() {
+        def session = sessionFactory.currentSession
+        session.flush()
+        session.clear()
+        propertyInstanceMap.get().clear()
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/AssetReportService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/AssetReportService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/AssetReportService.groovy	(revision 753)
@@ -0,0 +1,476 @@
+import net.kromhouts.HqlBuilder
+
+/**
+* Service class that encapsulates the business logic for Asset Reports.
+*/
+class AssetReportService {
+
+    boolean transactional = false
+
+    def authService
+    def dateUtilService
+//     def messageSource
+
+    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
+
+    def paramsMax = 100000
+
+    /**
+    * Selects and returns the assets and their details.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getAssetRegister(params, locale) {
+        def result = [:]
+
+        result.section = Section.get(params.section.id.toLong())
+        result.site = result.section.site
+
+        // Inner join used to return only attribTypes that are used by AssetExtendedAttributes.
+        // So the result is only asset extendedAttributeTypes.
+//         def attribTypesQ = new HqlBuilder().query {
+//             select 'distinct attribT.name'
+//             from 'AssetExtendedAttribute attrib',
+//                     'join attrib.extendedAttributeType as attribT'
+//             order 'by attribT.name asc'
+//         }
+
+        // All active ExtendedAttributes.
+        def attribTypesQ = new HqlBuilder().query {
+            select 'distinct attribT.name'
+            from 'ExtendedAttributeType attribT'
+            where 'attribT.isActive = true'
+            order 'by attribT.name asc'
+        }
+        result.attribTypes = ExtendedAttributeType.executeQuery(attribTypesQ.query, attribTypesQ.namedParams)
+
+        // A result is returned for every asset and for any extended attributes.
+        def q = new HqlBuilder().query {
+            select 'new map(asset.name as name',
+                        'asset.description as description',
+                        'asset.comment as comment',
+                        'attribT.name as attribType',
+                        'attrib.value as attribValue)'
+            from 'Asset asset',
+                    'left join asset.assetExtendedAttributes as attrib',
+                    'left join attrib.extendedAttributeType as attribT'
+            where 'asset.section = :section'
+                    namedParams.section = result.section
+            order 'by asset.name asc, attribT.name asc'
+        }
+        def assetResults = Asset.executeQuery(q.query, q.namedParams)
+
+        // Build the report table row for each asset.
+        // Rows are keyed by asset.name and the value is a Map of the attributes.
+        def rows = [:]
+        assetResults.each { assetResult ->
+            // Create row if it does not exist yet.
+            if(!rows.containsKey(assetResult.name)) {
+                rows[assetResult.name] = ['name':assetResult.name,
+                                                            'description':assetResult.description,
+                                                            'comment':assetResult.comment]
+
+                // Add all attribType columns.
+                result.attribTypes.each { column ->
+                    rows[assetResult.name][column] = ' '
+                }
+            }
+
+            // Assign value to column.
+            rows[assetResult.name][assetResult.attribType] = assetResult.attribValue
+        }
+
+        // The value of each row is the dataList used by the report table.
+        result.dataList = rows.collect {it.value}
+
+        // Success.
+        return result
+
+    } // getAssetRegister
+
+    /**
+    * Selects and returns an asset (or all) and its details.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getAssetDetail(params, locale) {
+        //def result = [:]
+        def result
+
+        //result.summaryOfCalculationMethod = ''
+
+        // A result is returned for every asset and for any extended attributes.
+        // The report then groups by asset.name
+        def q = new HqlBuilder().query {
+            select 'new map(asset.name as name',
+                        'asset.description as description',
+                        'asset.comment as comment',
+                        'attribT.name as attribType',
+                        'attrib.value as attribValue)'
+            from 'Asset asset',
+                    'left join asset.assetExtendedAttributes as attrib',
+                    'left join attrib.extendedAttributeType as attribT'
+            if(params.section instanceof Section) {
+                namedParams.section = params.section
+                where 'asset.section = :section'
+            }
+            order 'by asset.name asc, attribT.name asc'
+        }
+
+        // result.dataList = Asset.list()
+        result = Asset.executeQuery(q.query, q.namedParams)
+
+        // Success.
+        return result
+
+    } // getAssetDetail
+
+    /**
+    * Selects and returns level 1 sub items (aka machines or equipment) and their details.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getEquipmentRegister(params, locale) {
+        def result = [:]
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: [] ]
+            return result
+        }
+
+        result.section = Section.get(params.section.id.toLong())
+        result.site = result.section.site
+
+        result.startDate = params.startDate ?: dateUtilService.oneWeekAgo
+        result.endDate = params.endDate ?: dateUtilService.today
+        // Auto swap date range.
+        if(result.startDate > result.endDate) {
+            def tempStartDate = result.startDate
+            result.startDate = result.endDate
+            result.endDate = tempStartDate
+        }
+
+        result.startDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.startDate)
+        result.endDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.endDate)
+
+        // Inner join used to return only attribTypes that are used by AssetSubItemExtendedAttributes.
+        // So the result is only assetSubItem extendedAttributeTypes.
+//         def attribTypesQ = new HqlBuilder().query {
+//             select 'distinct attribT.name'
+//             from 'AssetSubItemExtendedAttribute attrib',
+//                     'join attrib.extendedAttributeType as attribT'
+//             order 'by attribT.name asc'
+//         }
+
+        // All active ExtendedAttributes.
+        def attribTypesQ = new HqlBuilder().query {
+            select 'distinct attribT.name'
+            from 'ExtendedAttributeType attribT'
+            where 'attribT.isActive = true'
+            order 'by attribT.name asc'
+        }
+        result.attribTypes = ExtendedAttributeType.executeQuery(attribTypesQ.query, attribTypesQ.namedParams)
+
+        // A useful list of assets without subItems to be given to the user.
+        def assetsWithoutEquipmentQ = new HqlBuilder().query {
+            select 'distinct asset'
+            from 'Asset asset',
+                    'left join asset.assetSubItems as assetSubItem'
+            where 'assetSubItem = null'
+                namedParams.section = result.section
+                and 'asset.section = :section'
+        }
+        result.assetsWithoutEquipment = Asset.executeQuery(assetsWithoutEquipmentQ.query, assetsWithoutEquipmentQ.namedParams)
+
+        // Subquery to count regulatory tasks.
+        def regulatoryTaskCountQ = new HqlBuilder().query {
+
+            select 'count (distinct task)'
+            from 'Task as task',
+                    'left join task.associatedAssets as associatedAsset'
+            where 'task.regulatoryRequirement = true'
+                and 'task.targetStartDate < :endDate'
+                and 'task.targetCompletionDate >= :startDate'
+                and '(task.primaryAsset.id = asset.id or associatedAsset.id = asset.id)'
+                and 'task.trash = false'
+        }
+
+        def totalRegulatoryTaskCountQ = regulatoryTaskCountQ.query
+
+        regulatoryTaskCountQ.and 'task.taskStatus.id = 3'
+        def completedRegulatoryTaskCountQ = regulatoryTaskCountQ.query
+
+        // A result is returned for every level 1 assetSubItem and for any extended attributes.
+        def q = new HqlBuilder().query {
+
+            select 'new map(asset.name as assetName',
+                        'assetSubItem.name as name',
+                        'assetSubItem.description as description',
+                        'assetSubItem.comment as comment',
+                        "0 as totalRegulatoryTaskCount",
+                        "0 as completedRegulatoryTaskCount",
+                        'attribT.name as attribType',
+                        'attrib.value as attribValue)'
+            from 'AssetSubItem assetSubItem',
+                    'inner join assetSubItem.assets as asset',
+                    'left join assetSubItem.assetSubItemExtendedAttributes as attrib',
+                    'left join attrib.extendedAttributeType as attribT'
+            where 'asset != null' // ensure that only level 1 assetSubItems are returned.
+                namedParams.section = result.section
+                and 'asset.section = :section'
+            order 'by asset.name asc, assetSubItem.name asc, attribT.name asc'
+        }
+        def equipmentResults = AssetSubItem.executeQuery(q.query, q.namedParams)
+
+        // A result is returned for every asset and for any extended attributes.
+        def assetResultsQ = new HqlBuilder().query {
+
+            // Subquery namedParams.
+            namedParams.startDate = result.startDate
+            namedParams.endDate = result.endDate+1
+
+            select 'new map(asset.name as assetName',
+                        "'   Asset Details' as name", // Place holder 'equipment' name, 3 leading spaces for sorting.
+                        'asset.description as description',
+                        'asset.comment as comment',
+                        "($totalRegulatoryTaskCountQ) as totalRegulatoryTaskCount",
+                        "($completedRegulatoryTaskCountQ) as completedRegulatoryTaskCount",
+                        'attribT.name as attribType',
+                        'attrib.value as attribValue)'
+            from 'Asset asset',
+                    'left join asset.assetExtendedAttributes as attrib',
+                    'left join attrib.extendedAttributeType as attribT'
+            where 'asset.section = :section'
+                    namedParams.section = result.section
+            order 'by asset.name asc, attribT.name asc'
+        }
+        def assetResults = Asset.executeQuery(assetResultsQ.query, assetResultsQ.namedParams)
+
+        // Add asset details to equipmentResults.
+        equipmentResults.addAll(assetResults)
+        equipmentResults.sort { p1, p2 -> p1.assetName.compareToIgnoreCase(p2.assetName) ?: p1.name.compareToIgnoreCase(p2.name) }
+
+        // Build the report table rows.
+        // Rows are keyed by equipmentResult.assetName+equipmentResult.name` while the value is a Map of the attributes.
+        // The report table then groups by assetName.
+        def rows = [:]
+        equipmentResults.each { equipmentResult ->
+
+            def rowKey = equipmentResult.assetName+equipmentResult.name
+
+            // Create new row if it does not exist yet.
+            if(!rows.containsKey(rowKey)) {
+                rows[rowKey] = ['assetName': equipmentResult.assetName,
+                                            'name':equipmentResult.name,
+                                            'description':equipmentResult.description,
+                                            'comment':equipmentResult.comment,
+                                            'Regulatory Task Completion': ' ']
+
+                // Add all attribType columns.
+                result.attribTypes.each { column ->
+                    rows[rowKey][column] = ' '
+                }
+
+                // Caluculate and assign RegulatoryTaskCompletion, only for Assets.
+                if(params.calculateRegulatoryTaskCompletion) {
+
+                    if(equipmentResult.totalRegulatoryTaskCount) {
+                        def percentComplete = (equipmentResult.completedRegulatoryTaskCount / equipmentResult.totalRegulatoryTaskCount)*100
+                        rows[rowKey]['Regulatory Task Completion'] = "${percentComplete.toInteger()}% (${equipmentResult.completedRegulatoryTaskCount}/${equipmentResult.totalRegulatoryTaskCount})"
+                    }
+                    else if(equipmentResult.name == '   Asset Details')
+                        rows[rowKey]['Regulatory Task Completion'] = 'N/A'
+                }
+
+            } // Create new row.
+
+            // Assign value to column.
+            rows[rowKey][equipmentResult.attribType] = equipmentResult.attribValue
+        } // each.
+
+        // The value of each row is the dataList used by the report table.
+        result.dataList = rows.collect {it.value}
+        // Print formatting, since we are done with these as objects.
+        result.attribTypes = result.attribTypes.join(', ')
+        result.assetsWithoutEquipment = result.assetsWithoutEquipment.collect {it.name}.join(', ')
+
+        // Success.
+        return result
+
+    } // getEquipmentRegister
+
+    /**
+    * Selects and returns assets regulatory requirements as specified in recurring regulatory tasks.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getRegulatoryRequirements(params, locale) {
+        def result = [:]
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: [] ]
+            return result
+        }
+
+        result.section = Section.get(params.section.id.toLong())
+        result.site = result.section.site
+
+        result.startDate = params.startDate ?: dateUtilService.oneWeekAgo
+        result.endDate = params.endDate ?: dateUtilService.today
+        // Auto swap date range.
+        if(result.startDate > result.endDate) {
+            def tempStartDate = result.startDate
+            result.startDate = result.endDate
+            result.endDate = tempStartDate
+        }
+
+        result.startDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.startDate)
+        result.endDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.endDate)
+
+        result.summary = "This report only selects primary assets and not associated assets. \n"
+        result.summary += "Tasks must have recurrence enabled and regulatory requirement set."
+
+        // Subquery to count subTasks..
+        def subTaskQ = new HqlBuilder().query {
+            select 'count(subTask)'
+            from 'task.subTasks as subTask'
+            where 'subTask.trash = false'
+                and 'subTask.targetStartDate < :endDate'
+                and 'subTask.targetCompletionDate >= :startDate'
+        }
+        def subTaskTotalQ = subTaskQ.query
+
+        subTaskQ.and 'subTask.taskStatus.id = 3' // Complete.
+        def subTaskCompletedQ = subTaskQ.query
+
+        def regulatoryTaskQ = new HqlBuilder().query {
+            select 'new map(primaryAsset.name as assetName',
+                        'primaryAsset.description as assetDescription',
+                        'primaryAsset.isActive as assetIsActive',
+                        'task.id as taskId',
+                        'task.description as taskDescription',
+                        "($subTaskTotalQ) as subTaskTotalCount",
+                        "($subTaskCompletedQ) as subTaskCompletedCount)"
+                        namedParams.startDate = result.startDate
+                        namedParams.endDate = result.endDate
+            from 'Task task',
+                    'left join task.primaryAsset as primaryAsset',
+                    'left join task.taskRecurringSchedule as taskRecurringSchedule'
+            where 'task.regulatoryRequirement = true'
+                and 'taskRecurringSchedule.enabled = true'
+                and 'task.trash = false'
+                        namedParams.sectionId = result.section.id
+                and 'primaryAsset.section.id = :sectionId'
+        }
+        result.tasks = Task.executeQuery(regulatoryTaskQ.query, regulatoryTaskQ.namedParams)
+
+        // Build the report table row for each task.
+        result.tasks.each { task ->
+
+            // Caluculate percentages and build description.
+            def percentComplete
+            def completionFigures
+            if(task.subTaskTotalCount) {
+                percentComplete = (task.subTaskCompletedCount / task.subTaskTotalCount) * 100
+                task.completionFigures = "${percentComplete.toInteger()}% ($task.subTaskCompletedCount/$task.subTaskTotalCount)"
+            }
+            else
+                task.completionFigures = '0 sub tasks in date range'
+        } // tasks.each
+
+        result.dataList = result.tasks
+        result.dataList.sort { p1, p2 -> p1.assetName.compareToIgnoreCase(p2.assetName) }
+
+        // Success.
+        return result
+
+    } // getRegulatoryRequirements
+
+    /**
+    * Selects and returns assets mandatory requirements as specified in recurring mandatory tasks.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getMandatoryRequirements(params, locale) {
+        def result = [:]
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: [] ]
+            return result
+        }
+
+        result.section = Section.get(params.section.id.toLong())
+        result.site = result.section.site
+
+        result.startDate = params.startDate ?: dateUtilService.oneWeekAgo
+        result.endDate = params.endDate ?: dateUtilService.today
+        // Auto swap date range.
+        if(result.startDate > result.endDate) {
+            def tempStartDate = result.startDate
+            result.startDate = result.endDate
+            result.endDate = tempStartDate
+        }
+
+        result.startDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.startDate)
+        result.endDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.endDate)
+
+        result.summary = "This report only selects primary assets and not associated assets. \n"
+        result.summary += "Tasks must have recurrence enabled and mandatory requirement set."
+
+        // Subquery to count subTasks..
+        def subTaskQ = new HqlBuilder().query {
+            select 'count(subTask)'
+            from 'task.subTasks as subTask'
+            where 'subTask.trash = false'
+                and 'subTask.targetStartDate < :endDate'
+                and 'subTask.targetCompletionDate >= :startDate'
+        }
+        def subTaskTotalQ = subTaskQ.query
+
+        subTaskQ.and 'subTask.taskStatus.id = 3' // Complete.
+        def subTaskCompletedQ = subTaskQ.query
+
+        def mandatoryTaskQ = new HqlBuilder().query {
+            select 'new map(primaryAsset.name as assetName',
+                        'primaryAsset.description as assetDescription',
+                        'primaryAsset.isActive as assetIsActive',
+                        'task.id as taskId',
+                        'task.description as taskDescription',
+                        "($subTaskTotalQ) as subTaskTotalCount",
+                        "($subTaskCompletedQ) as subTaskCompletedCount)"
+                        namedParams.startDate = result.startDate
+                        namedParams.endDate = result.endDate
+            from 'Task task',
+                    'left join task.primaryAsset as primaryAsset',
+                    'left join task.taskRecurringSchedule as taskRecurringSchedule'
+            where 'task.mandatoryRequirement = true'
+                and 'taskRecurringSchedule.enabled = true'
+                and 'task.trash = false'
+                        namedParams.sectionId = result.section.id
+                and 'primaryAsset.section.id = :sectionId'
+        }
+        result.tasks = Task.executeQuery(mandatoryTaskQ.query, mandatoryTaskQ.namedParams)
+
+        // Build the report table row for each task.
+        result.tasks.each { task ->
+
+            // Caluculate percentages and build description.
+            def percentComplete
+            def completionFigures
+            if(task.subTaskTotalCount) {
+                percentComplete = (task.subTaskCompletedCount / task.subTaskTotalCount) * 100
+                task.completionFigures = "${percentComplete.toInteger()}% ($task.subTaskCompletedCount/$task.subTaskTotalCount)"
+            }
+            else
+                task.completionFigures = '0 sub tasks in date range'
+        } // tasks.each
+
+        result.dataList = result.tasks
+        result.dataList.sort { p1, p2 -> p1.assetName.compareToIgnoreCase(p2.assetName) }
+
+        // Success.
+        return result
+
+    } // getMandatoryRequirements
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/AssetService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/AssetService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/AssetService.groovy	(revision 753)
@@ -0,0 +1,355 @@
+
+import org.apache.commons.lang.WordUtils
+
+class AssetService {
+
+    boolean transactional = false
+
+    def sessionFactory
+
+    def assetSubItemService
+
+    /**
+    * Determines and returns a possible list of asset sub items.
+    * @returns A list of the possible assetSubItems.
+    */
+    def possibleAssetSubItems() {
+        def criteria = AssetSubItem.createCriteria()
+        def possibleAssetSubItems = criteria.list() {
+            and {
+                eq('isActive', true)
+                isNull("parentItem")
+                }
+        }
+    }
+
+    def delete(params) {
+        Asset.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.assetInstance && m.field)
+                    result.assetInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Asset", params.id] ]
+                return result
+            }
+
+            result.assetInstance = Asset.get(params.id)
+
+            if(!result.assetInstance)
+                return fail(code:"default.not.found")
+
+            if(result.assetInstance.maintenanceActions)
+                return fail(code:"maintenanceActions.still.associated")
+
+            // Remove orphan assetSubItems.
+            def assetSubItems = new ArrayList(result.assetInstance.assetSubItems) // avoid ConcurrentModificationException.
+            def r
+            for(assetSubItem in assetSubItems) {
+                result.assetInstance.removeFromAssetSubItems(assetSubItem)
+                if(!assetSubItem.assets && !assetSubItem.parentItem) {
+                    r = assetSubItemService.delete(id: assetSubItem.id)
+                    if(r.error) {
+                        log.debug r.error
+                        fail(code:"asset.subItems.delete.failure")
+                        break
+                    }
+                }
+            }
+
+            if(result.error)
+                return result
+
+            // Success.
+            // We have handled all the foreign keys so the delete should go forward.
+            // Can't flush here due to cascading from Section and Site.
+            // And without flush there is no point it trying to catch the dao.DataIntegrityViolationException
+            // since that will only happen after leaving the transaction.
+            result.assetInstance.delete()
+            return result
+
+        } // end withTransaction
+    } // end delete()
+
+    def create(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["Asset", params.id] ]
+            return result
+        }
+
+        result.assetInstance = new Asset()
+        result.assetInstance.properties = params
+
+        // success
+        return result
+    }
+
+    def copy(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["Asset", params.id] ]
+            return result
+        }
+
+        result.assetToCopy = Asset.get(params.assetToCopy?.id)
+
+        if(!result.assetToCopy)
+            return fail(code: "asset.copy.asset.required")
+
+        result.assetInstance = new Asset(name: result.assetToCopy.name,
+                                                            description: result.assetToCopy.description,
+                                                            comment: result.assetToCopy.comment,
+                                                            section: result.assetToCopy.section)
+
+        result.assetInstance.properties = params
+
+        // success
+        return result
+    }
+
+    def save(params) {
+        def result = [:]
+        def fail = { Map m ->
+            if(result.assetInstance && m.field) 
+                result.assetInstance.errors.rejectValue(m.field, m.code)
+            result.error = [ code: m.code, args: ["Asset", params.id] ]
+            return result
+        }
+
+        result.assetInstance = new Asset(params)
+
+        use(WordUtils) {
+            result.assetInstance.name = result.assetInstance.name.capitalize()
+            result.assetInstance.description = result.assetInstance.description.capitalize()
+        }
+
+        if(result.assetInstance.hasErrors() || !result.assetInstance.save(flush: true))
+            return fail(code:"default.create.failure")
+
+        // success
+        return result
+    }
+
+    def saveCopy(params) {
+        Asset.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.assetInstance && m.field)
+                    result.assetInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Asset", params.id] ]
+                return result
+            }
+
+            result.assetToCopy = Asset.get(params.assetToCopy?.id)
+            if(!result.assetToCopy)
+                return fail(code:"default.not.found")
+
+            if(!params.copyMethod)
+                fail(code:"asset.copy.method.required")
+
+            result.assetInstance =  new Asset(params)
+
+            if(result.assetInstance.hasErrors() || !result.assetInstance.save())
+                return fail(code:"default.create.failure")
+
+            def assetSubItemInstance1
+
+            // Copy subItems from level 2 and bellow.
+            def copyAssetSubItem = { assetSubItemToCopy, parentItem ->
+                def nextCount = AssetSubItem.count() + 1
+                def baseName = assetSubItemToCopy.name.split('\\(id:')[0]
+                def name = baseName +'(id:'+nextCount+')'
+                def assetSubItemInstance = new AssetSubItem(name: name,
+                                                                                            description: assetSubItemToCopy.description,
+                                                                                            parentItem: parentItem)
+
+                if(assetSubItemInstance.hasErrors() || !assetSubItemInstance.save())
+                    return fail(code:"asset.copy.subItem.create.failure")
+
+                def i = 0
+                for(assetSubItem in assetSubItemToCopy.subItems) {
+                    call(assetSubItem, assetSubItemInstance)
+                    // Protect against endless recurrsion.
+                    i++
+                    if(i > 100)
+                        fail(code:"asset.copy.subItem.too.many.failure")
+                    // Stop if an error is flagged.
+                    if(result.error)
+                        break
+                }
+            } //copyAssetSubItem
+
+            // Copy the 1st level of subItems.
+            def copyAssetSubItem1 = { assetSubItemToCopy ->
+                def nextCount = AssetSubItem.count() + 1
+                def baseName = assetSubItemToCopy.name.split('\\(id:')[0]
+                def name = baseName +'(id:'+nextCount+')'
+                assetSubItemInstance1 = new AssetSubItem(name: name,
+                                                                                        description: assetSubItemToCopy.description,
+                                                                                        asset: result.assetInstance)
+
+                if(assetSubItemInstance1.hasErrors() || !assetSubItemInstance1.save())
+                    return fail(code:"asset.copy.subItem.create.failure")
+
+                result.assetInstance.addToAssetSubItems(assetSubItemInstance1)
+
+                def i = 0
+                for(assetSubItem in assetSubItemToCopy.subItems) {
+                    copyAssetSubItem(assetSubItem, assetSubItemInstance1)
+                    // Protect against endless recurrsion.
+                    i++
+                    if(i > 100)
+                        fail(code:"asset.copy.subItem.too.many.failure")
+                    // Stop if an error is flagged.
+                    if(result.error)
+                        break
+                }
+            } //copyAssetSubItem1
+
+            def linkAssetSubItem = { assetSubItemToLink ->
+                result.assetInstance.addToAssetSubItems(assetSubItemToLink)
+            }
+
+            def i = 0
+            for(assetSubItem in result.assetToCopy.assetSubItems) {
+
+                if(params.copyMethod == "copy")
+                    copyAssetSubItem1(assetSubItem)
+                else
+                    linkAssetSubItem(assetSubItem)
+                // Protect against endless recurrsion.
+                i++
+                if(i > 100)
+                    fail(code:"asset.copy.subItem.too.many.failure")
+                // Stop if an error is flagged.
+                if(result.error)
+                    break
+            }
+
+            // Success or not.
+            return result
+
+        } // end withTransaction
+    } // end saveCopySrvce
+
+    /**
+    * Create recommended extended attributes for all assets.
+    */
+    def createRecommendedExtendedAttributes() {
+        def result = [:]
+
+        def hibernateSession = sessionFactory.currentSession
+
+        def assets = Asset.list()
+        def locationDescription = ExtendedAttributeType.findByName("Location Description")
+        def ecr = ExtendedAttributeType.findByName("ecr")
+        def assetNumber = ExtendedAttributeType.findByName("Asset Number")
+        def assetCondition = ExtendedAttributeType.findByName("Asset Condition")
+        def maintenancePercentComplete = ExtendedAttributeType.findByName("Maintenance % Completion")
+        def registrationRequired = ExtendedAttributeType.findByName("Registration Required")
+        def registrationExpiryDate =  ExtendedAttributeType.findByName("Registration Expiry Date")
+        def regulatoryRequirement = ExtendedAttributeType.findByName("Regulatory Requirement")
+        def riskLevel = ExtendedAttributeType.findByName("Risk Level")
+        def safeWorkProcedure = ExtendedAttributeType.findByName("Safe Work Procedure")
+
+        for(asset in assets) {
+
+            def attributeTypes = asset.assetExtendedAttributes.collect {it.extendedAttributeType}
+
+            //AssetExtendedAttribute
+            def assetExtendedAttributeInstance
+
+            if(!attributeTypes.contains(locationDescription)) {
+                //AssetExtendedAttribute #1
+                assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Not Specified",
+                                                                                                                    asset: asset,
+                                                                                                                    extendedAttributeType: locationDescription)
+                assetExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(ecr)) {
+                //AssetExtendedAttribute #2
+                assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Not Specified",
+                                                                                                                    asset: asset,
+                                                                                                                    extendedAttributeType: ecr)
+                assetExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(assetNumber)) {
+                //AssetExtendedAttribute #3
+                assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Not Specified",
+                                                                                                                    asset: asset,
+                                                                                                                    extendedAttributeType: assetNumber)
+                assetExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(assetCondition)) {
+                //AssetExtendedAttribute #4
+                assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Not Specified",
+                                                                                                                    asset: asset,
+                                                                                                                    extendedAttributeType: assetCondition)
+                assetExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(maintenancePercentComplete)) {
+                //AssetExtendedAttribute #5
+                assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "TBA",
+                                                                                                                    asset: asset,
+                                                                                                                    extendedAttributeType: maintenancePercentComplete)
+                assetExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(registrationRequired)) {
+                //AssetExtendedAttribute #6
+                assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Not Specified",
+                                                                                                                    asset: asset,
+                                                                                                                    extendedAttributeType: registrationRequired)
+                assetExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(registrationExpiryDate)) {
+                //AssetExtendedAttribute #7
+                assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Not Specified",
+                                                                                                                    asset: asset,
+                                                                                                                    extendedAttributeType:registrationExpiryDate)
+                assetExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(regulatoryRequirement)) {
+                //AssetExtendedAttribute #8
+                assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Not Specified",
+                                                                                                                    asset: asset,
+                                                                                                                    extendedAttributeType: regulatoryRequirement)
+                assetExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(riskLevel)) {
+                //AssetExtendedAttribute #9
+                assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Not Specified",
+                                                                                                                    asset: asset,
+                                                                                                                    extendedAttributeType: riskLevel)
+                assetExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(safeWorkProcedure)) {
+                //AssetExtendedAttribute #10
+                assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Not Specified",
+                                                                                                                    asset: asset,
+                                                                                                                    extendedAttributeType: safeWorkProcedure)
+                assetExtendedAttributeInstance.save()
+            }
+
+            hibernateSession.flush()
+
+        } // for
+
+        // Success.
+        return result
+
+    } // createRecommendedExtendedAttributes()
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/AssetSubItemService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/AssetSubItemService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/AssetSubItemService.groovy	(revision 753)
@@ -0,0 +1,205 @@
+
+import net.kromhouts.HqlBuilder
+import org.apache.commons.lang.WordUtils
+
+class AssetSubItemService {
+
+    boolean transactional = false
+
+    def sessionFactory
+
+    /**
+    * Determines and returns sorted list of possible parent items.
+    * @param assetSubItemInstance The instance to prepare the list for.
+    * @returns A list of the possible parentItems.
+    */
+    def possibleParentItems(assetSubItemInstance) {
+        def criteria = AssetSubItem.createCriteria()
+        def possibleParentItems = criteria.list() {
+            and {
+                eq('isActive', true)
+                ne('id', assetSubItemInstance.id)
+                assetSubItemInstance.subItems.each() { notEqual('id', it.id) }
+                }
+        }
+        possibleParentItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+    }
+
+    def delete(params) {
+        AssetSubItem.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.assetSubItemInstance && m.field)
+                    result.assetSubItemInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["AssetSubItem", params.id] ]
+                return result
+            }
+
+            result.assetSubItemInstance = AssetSubItem.get(params.id)
+
+            if(!result.assetSubItemInstance)
+                return fail(code:"default.not.found")
+
+            for(subItem in result.assetSubItemInstance.subItems) {
+                if(subItem.maintenanceActions)
+                    fail(code:"maintenanceActions.still.associated.subItem")
+            }
+
+            if(result.error)
+                return result
+
+            if(result.assetSubItemInstance.maintenanceActions)
+                return fail(code:"maintenanceActions.still.associated")
+
+            if(result.assetSubItemInstance.assets)
+                return fail(code:"assetSubItem.assets.associated")
+
+            // We have handled all the foreign keys so the delete should go forward.
+            // Can't flush here due to cascading from Section and Site.
+            // And without flush there is no point it trying to catch the dao.DataIntegrityViolationException
+            // since that will only happen after leaving the transaction.
+            result.assetSubItemInstance.delete()
+            return result //Success.
+
+        } // withTransaction
+    }
+
+    def create(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["AssetSubItem", params.id] ]
+            return result
+        }
+
+        result.assetSubItemInstance = new AssetSubItem()
+        result.assetSubItemInstance.properties = params
+
+        // pass in an asset to link to if provided.
+        if(params.asset?.id)
+            result.assetInstance = Asset.get(params.asset.id)
+
+        // success
+        return result
+    }
+
+    def save(params) {
+        AssetSubItem.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.assetSubItemInstance && m.field)
+                    result.assetSubItemInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["AssetSubItem", params.id] ]
+                return result
+            }
+
+            result.assetSubItemInstance = new AssetSubItem(params)
+
+            use(WordUtils) {
+                result.assetSubItemInstance.name = result.assetSubItemInstance.name.capitalize()
+                result.assetSubItemInstance.description = result.assetSubItemInstance.description.capitalize()
+            }
+
+            if(params.asset?.id) {
+                result.assetInstance = Asset.get(params.asset.id)
+
+                if(!result.assetInstance)
+                    return fail(code:"assetSubItem.asset.not.found")
+            }
+
+            if(result.assetSubItemInstance.hasErrors() || !result.assetSubItemInstance.save(flush: true))
+                return fail(code:"default.create.failure")
+
+            if(result.assetInstance)
+                result.assetInstance.addToAssetSubItems(result.assetSubItemInstance)
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    } // save()
+
+    /**
+    * Get a list of level 1 assetSubItems.
+    * @returns By default all level 1 assetSubItems are returned.
+    */
+    def getLevel1AssetSubItems(params) {
+
+        // A result is returned for every level 1 assetSubItem.
+        def q = new HqlBuilder().query {
+            select 'assetSubItem'
+            from 'AssetSubItem assetSubItem',
+                    'inner join assetSubItem.assets as asset'
+            where 'asset != null' // ensure that only level 1 assetSubItems are returned.
+        }
+        def assetSubItems = AssetSubItem.executeQuery(q.query, q.namedParams)
+
+    }
+
+    /**
+    * Create recommended extended attributes for all level 1 subItems.
+    */
+    def createRecommendedExtendedAttributes() {
+        def result = [:]
+
+        def hibernateSession = sessionFactory.currentSession
+
+        def assetSubItems = getLevel1AssetSubItems()
+
+        def manufacturer = ExtendedAttributeType.findByName("Manufacturer")
+        def modelNumber = ExtendedAttributeType.findByName("Model Number")
+        def serialNumber = ExtendedAttributeType.findByName("Serial Number")
+        def manufacturedDate = ExtendedAttributeType.findByName("Manufactured Date")
+
+        for(assetSubItem in assetSubItems) {
+
+            def attributeTypes = assetSubItem.assetSubItemExtendedAttributes.collect {it.extendedAttributeType}
+
+            //AssetSubItemExtendedAttribute
+            def assetSubItemExtendedAttributeInstance
+
+            if(!attributeTypes.contains(manufacturer)) {
+                //AssetSubItemExtendedAttribute #1
+                assetSubItemExtendedAttributeInstance = new AssetSubItemExtendedAttribute(value: "Not Specified",
+                                                                                                                    assetSubItem: assetSubItem,
+                                                                                                                    extendedAttributeType: manufacturer)
+                assetSubItemExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(modelNumber)) {
+                //AssetSubItemExtendedAttribute #2
+                assetSubItemExtendedAttributeInstance = new AssetSubItemExtendedAttribute(value: "Not Specified",
+                                                                                                                    assetSubItem: assetSubItem,
+                                                                                                                    extendedAttributeType: modelNumber)
+                assetSubItemExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(serialNumber)) {
+                //AssetSubItemExtendedAttribute #3
+                assetSubItemExtendedAttributeInstance = new AssetSubItemExtendedAttribute(value: "Not Specified",
+                                                                                                                    assetSubItem: assetSubItem,
+                                                                                                                    extendedAttributeType: serialNumber)
+                assetSubItemExtendedAttributeInstance.save()
+            }
+
+            if(!attributeTypes.contains(manufacturedDate)) {
+                //AssetSubItemExtendedAttribute #4
+                assetSubItemExtendedAttributeInstance = new AssetSubItemExtendedAttribute(value: "Not Specified",
+                                                                                                                    assetSubItem: assetSubItem,
+                                                                                                                    extendedAttributeType: manufacturedDate)
+                assetSubItemExtendedAttributeInstance.save()
+            }
+
+            hibernateSession.flush()
+
+        } // for
+
+        // Success.
+        return result
+
+    } // createRecommendedExtendedAttributes()
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/AssetTreeService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/AssetTreeService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/AssetTreeService.groovy	(revision 753)
@@ -0,0 +1,525 @@
+class AssetTreeService {
+
+    boolean transactional = false
+
+    def js = new JsUtilService()
+
+    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
+
+    /** General */
+    def nameDescriptionSeperator = ' -- '
+
+    /** Html class and id settings */
+    def buttonHtmlClass = 'tree_button'
+    def paneHtmlClass = 'overlayPane'
+    def paneHtmlId = 'assetTreePane'
+    def paneCloseHtmlClass = 'pane_close'
+    def tableDivHtmlClass = 'tree'
+    def tableHtmlId = 'assetTreeTable'
+    def tableLoadingImgId = 'assetTreeLoadingImg'
+
+    /** Imgs */
+    def treeRootImg = ''
+    def addImg = ''
+    def copyImg = ''
+    def bulletTreePlusImg = ''
+    def bulletTreeMinusImg = ''
+    def dashImg = ''
+    def closeImg = ''
+
+    /** Urls */
+    def assetTreeActionUrl = ''
+    def saveAssetTreeStatusActionUrl = ''
+
+    /** Links */
+    def siteCreateBaseLink = ''
+    def siteShowBaseLink = ''
+    def siteEditBaseLink = ''
+    def sectionCreateBaseLink = ''
+    def sectionShowBaseLink = ''
+    def sectionEditBaseLink = ''
+    def assetCreateBaseLink = ''
+    def assetShowBaseLink = ''
+    def assetEditBaseLink = ''
+    def assetCopyBaseLink = ''
+    def assetSubItemCreateBaseLink = ''
+    def assetSubItemCreateWithParentBaseLink = ''
+    def assetSubItemShowBaseLink = ''
+    def assetSubItemEditBaseLink = ''
+
+    /**
+    * Initialise some class wide variables.
+    * This has been done to optimise since g.link and g.resource calls are expensive.
+    * This can't be done by class construction since some of the metaclass stuff is not available yet, e.g. 'out' etc.
+    * Initialise can't be called from BootStrap.
+    */
+    def initialise() {
+        log.debug "Initialise asset tree variables."
+
+        // Imgs.
+        treeRootImg = g.resource(dir:'images/skin',file:'chart_organisation.png')
+        addImg = g.resource(dir:'images/skin',file:'database_add.png')
+        copyImg = g.resource(dir:'images/skin',file:'page_copy.png')
+        bulletTreePlusImg = g.resource(dir:'images/skin',file:'bullet_tree_plus.png')
+        bulletTreeMinusImg = g.resource(dir:'images/skin',file:'bullet_tree_minus.png')
+        dashImg = g.resource(dir:'images/skin',file:'hline_short.png')
+        closeImg = g.resource(dir:'images/skin',file:'cross.png')
+
+        // Urls.
+        assetTreeActionUrl = g.createLink(controller: 'assetDetailed', action: 'assetTree')
+        saveAssetTreeStatusActionUrl = g.createLink(controller: 'assetDetailed', action: 'saveAssetTreeStatus')
+
+        // Links
+        siteCreateBaseLink = g.createLink(controller: 'siteDetailed', action: 'create').toString()
+        siteShowBaseLink = g.createLink(controller: 'siteDetailed', action: 'show').toString()
+        siteEditBaseLink = g.createLink(controller: 'siteDetailed', action: 'edit').toString()
+        sectionCreateBaseLink = g.createLink(controller: 'sectionDetailed', action: 'create').toString()
+        sectionShowBaseLink = g.createLink(controller: 'sectionDetailed', action: 'show').toString()
+        sectionEditBaseLink = g.createLink(controller: 'sectionDetailed', action: 'edit').toString()
+        assetCreateBaseLink = g.createLink(controller: 'assetDetailed', action: 'create').toString()
+        assetShowBaseLink = g.createLink(controller: 'assetDetailed', action: 'show').toString()
+        assetEditBaseLink = g.createLink(controller: 'assetDetailed', action: 'edit').toString()
+        assetCopyBaseLink = g.createLink(controller: 'assetDetailed', action: 'copy').toString()
+        assetSubItemCreateBaseLink = g.createLink(controller: 'assetSubItemDetailed', action: 'create').toString()
+        assetSubItemCreateWithParentBaseLink = g.createLink(controller: 'assetSubItemDetailed', action: 'create').toString()
+        assetSubItemShowBaseLink = g.createLink(controller: 'assetSubItemDetailed', action: 'show').toString()
+        assetSubItemEditBaseLink = g.createLink(controller: 'assetSubItemDetailed', action: 'edit').toString()
+        // Success.
+        return true
+    }
+
+    /** Name and Description Formatting */
+
+    def name(obj) {
+        obj.name.encodeAsHTML()
+    }
+
+    def description(obj) {
+        def s =  obj.description.encodeAsHTML()
+        s = s? (nameDescriptionSeperator + s) : ''
+    }
+
+    /**
+    * Build and return the asset tree button.
+    * Built here instead of directly in the taglib since we may need to initialise.
+    */
+    def buildAssetTreeButton(attrs) {
+
+        // Self initialisation ;-)
+        if(!treeRootImg)
+            initialise()
+
+        def sw = new StringWriter()
+        def mkp = new groovy.xml.MarkupBuilder(sw)
+
+        mkp.div(class: buttonHtmlClass) {
+            a( href: hrefShowPane() ) {
+                img(src: treeRootImg)
+            }
+        } // mkp
+
+        return sw.toString()
+    }
+
+    /**
+    * Build and return the empty asset tree pane, ready for populating by ajax call to buildAssetTree.
+    * Built here instead of directly in the taglib since we may need to initialise.
+    */
+    def buildAssetTreePane(attrs) {
+
+        // Self initialisation ;-)
+        if(!treeRootImg)
+            initialise()
+
+        def sw = new StringWriter()
+        def mkp = new groovy.xml.MarkupBuilder(sw)
+
+        mkp.div(class: paneHtmlClass, id: paneHtmlId, style: 'display:none;') {
+            div(class: paneCloseHtmlClass) {
+                a( href: js.toggle(paneHtmlId) ) {
+                    img(src: closeImg)
+                }
+            }
+
+            div(class: tableDivHtmlClass) {
+                table(id: tableHtmlId) {
+                    tr() {
+                        td(valign: 'top', class: 'value') {
+                            ul() {
+                                img(src: treeRootImg, id: tableLoadingImgId, alt: 'TreeRoot')
+                                li() {
+                                } // li
+                            } // ul
+                        } // td
+                    } // tr
+                } // table
+            } // div
+        } // mkp
+
+        return sw.toString()
+
+    } // buildAssetPane
+
+    /**
+    * Build and return the asset tree table.
+    * To be used in conjunction with AssetTreeTagLib which inserts the wrapper div built by buildAssetTreePane().
+    * This table replaces the contents of the wrapper div.
+    * @returns The asset tree table as a String
+    */
+    def buildAssetTree(params, session) {
+
+        def startedAt = System.currentTimeMillis()
+
+        // Self initialisation ;-)
+        if(!treeRootImg)
+            initialise()
+
+        def sites = Site.withCriteria {
+            eq("isActive", true)
+        }
+
+        def visibleBranches = session.assetTreeVisibleBranches ? session.assetTreeVisibleBranches.tokenize(',') : []
+
+        def branchStyle = { branchId ->
+            if(visibleBranches.contains(branchId))
+                ''
+            else
+                'display:none;'
+        }
+
+        def branchImg = { branchId ->
+            if(visibleBranches.contains(branchId))
+                bulletTreeMinusImg
+            else
+                bulletTreePlusImg
+        }
+
+        def divIdCount = 0
+        def divId = ''
+        def nextDivId = {
+            divIdCount++
+            divId = 'assetTreeBranch'+divIdCount
+        }
+
+        def sw = new StringWriter()
+        def mkp = new groovy.xml.MarkupBuilder(sw)
+
+        // Offer a site create link if no sites are found.
+        if(!sites) {
+            mkp.div(class: tableDivHtmlClass) {
+
+                div(class: paneCloseHtmlClass) {
+                    a( href: js.toggle(paneHtmlId) ) {
+                        img(src: closeImg)
+                    }
+                }
+
+                table(id: tableHtmlId) {
+                    tr() {
+                        td( valign: 'top', class: 'value') {
+                            ul() {
+                                img(src: treeRootImg, alt: 'TreeRoot')
+                                li() {
+                                    a(href: siteCreateBaseLink) {
+                                        img(src: addImg, alt: 'Add', title: 'Add Site')
+                                    }
+                                } // li
+                            } // ul
+                        } // td
+                    } // tr
+                } // table
+
+                div( class: 'buttons') {
+                    span(class: 'button') {
+                        input( type: 'button', value: g.message(code: 'default.close.text'), onclick: js.toggle(paneHtmlId, "onclick") )
+                    }
+                } // button div
+            } // mkp
+            return sw.toString()
+        } // if(!sites)
+
+
+        // The main populated table.
+        /// @todo: use a loop for the subItem levels.
+        mkp.div(class: tableDivHtmlClass) {
+
+            div(class: paneCloseHtmlClass) {
+                a( href: hrefHideAndSavePane() ) {
+                    img(src: closeImg)
+                }
+            }
+
+            table(id: tableHtmlId) {
+                tr() {
+                    td(valign: 'top', class: 'value') {
+                        ul() {
+                            img(src: treeRootImg, alt: 'TreeRoot')
+                            for(site in sites.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
+                                li() {
+                                    if(site.sections) {
+                                        a(href: toggleBranch(nextDivId()) ) {
+                                            img( src: branchImg(divId), id: divId+'img' )
+                                        }
+                                    }
+                                    else
+                                        img(src: dashImg)
+                                    a( href: siteShowLink(site.id), onclick: onclickHideAndSavePane() ) {
+                                        yieldUnescaped( name(site)  )
+                                    }
+                                    yieldUnescaped( description(site)  )
+                                    a(href: sectionCreateLink(site.id), onclick: onclickHideAndSavePane()) {
+                                        img(src: addImg, alt: 'Add', title: 'Add Section')
+                                    }
+                                }
+                                if(site.sections) {
+                                    div( id: divId, style: branchStyle(divId) ) {
+                                        ul() {
+                                            for(section in site.sections.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
+                                                li() {
+                                                    if(section.assets) {
+                                                        a( href: toggleBranch(nextDivId()) ) {
+                                                            img(src: branchImg(divId), id: divId+'img' )
+                                                        }
+                                                    }
+                                                    else
+                                                        img(src: dashImg)
+                                                    a( href: sectionShowLink(section.id), onclick: onclickHideAndSavePane() ) {
+                                                        yieldUnescaped( name(section) )
+                                                    }
+                                                    yieldUnescaped( description(section)  )
+                                                    a(href: assetCreateLink(section.id), onclick: onclickHideAndSavePane()) {
+                                                        img(src: addImg, alt: 'Add', title: 'Add Asset')
+                                                    }
+                                                }
+
+                                                if(section.assets) {
+                                                    div( id: divId, style: branchStyle(divId) ) {
+                                                        ul() {
+                                                            for(asset in section.assets.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
+                                                                li() {
+                                                                    if(asset.assetSubItems) {
+                                                                        a( href: toggleBranch(nextDivId()) ) {
+                                                                            img(src: branchImg(divId), id: divId+'img' )
+                                                                        }
+                                                                    }
+                                                                    else
+                                                                        img(src: dashImg)
+                                                                    a( href: assetShowLink(asset.id), onclick: onclickHideAndSavePane() ) {
+                                                                        yieldUnescaped( name(asset) )
+                                                                    }
+                                                                    yieldUnescaped( description(asset) )
+                                                                    a(href: assetSubItemCreateLink(asset.id), onclick: onclickHideAndSavePane()) {
+                                                                        img(src: addImg, alt: 'Add', title: 'Add Sub Item')
+                                                                    }
+                                                                    a(href: assetCopyLink(asset.id), onclick: onclickHideAndSavePane()) {
+                                                                        img(src: copyImg, alt: 'Add', title: 'Copy Asset')
+                                                                    }
+                                                                } // li
+
+                                                                if(asset.assetSubItems) {
+                                                                    div( id: divId, style: branchStyle(divId) ) {
+                                                                        ul() {
+                                                                            for(assetSubItemL1 in asset.assetSubItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
+                                                                                li() {
+                                                                                    if(assetSubItemL1.subItems) {
+                                                                                        a( href: toggleBranch(nextDivId()) ) {
+                                                                                            img(src: branchImg(divId), id: divId+'img' )
+                                                                                        }
+                                                                                    }
+                                                                                    else
+                                                                                        img(src: dashImg)
+                                                                                    a( href: assetSubItemShowLink(assetSubItemL1.id), onclick: onclickHideAndSavePane() ) {
+                                                                                        yieldUnescaped( name(assetSubItemL1) )
+                                                                                    }
+                                                                                    yieldUnescaped( description(assetSubItemL1) )
+                                                                                    a(href: assetSubItemCreateWithParentLink(assetSubItemL1.id), onclick: onclickHideAndSavePane()) {
+                                                                                        img(src: addImg, alt: 'Add', title: 'Add Sub Item')
+                                                                                    }
+                                                                                } // li
+
+                                                                                if(assetSubItemL1.subItems) {
+                                                                                    div( id: divId, style: branchStyle(divId) ) {
+                                                                                        ul() {
+                                                                                            for(assetSubItemL2 in assetSubItemL1.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
+                                                                                                li() {
+                                                                                                    if(assetSubItemL2.subItems) {
+                                                                                                        a( href: toggleBranch(nextDivId()) ) {
+                                                                                                            img( src: branchImg(divId), id: divId+'img' )
+                                                                                                        }
+                                                                                                    }
+                                                                                                    else
+                                                                                                        img(src: dashImg)
+                                                                                                    a( href: assetSubItemShowLink(assetSubItemL2.id), onclick: onclickHideAndSavePane() ) {
+                                                                                                        yieldUnescaped( name(assetSubItemL2) )
+                                                                                                    }
+                                                                                                    yieldUnescaped( description(assetSubItemL2) )
+                                                                                                    a(href: assetSubItemCreateWithParentLink(assetSubItemL2.id), onclick: onclickHideAndSavePane()) {
+                                                                                                        img(src: addImg, alt: 'Add', title: 'Add Sub Item')
+                                                                                                    }
+                                                                                                } // li
+
+                                                                                                if(assetSubItemL2.subItems) {
+                                                                                                    div( id: divId, style: branchStyle(divId) ) {
+                                                                                                        ul() {
+                                                                                                            for(assetSubItemL3 in assetSubItemL2.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
+                                                                                                                li() {
+                                                                                                                    if(assetSubItemL3.subItems) {
+                                                                                                                        a( href: toggleBranch(nextDivId()) ) {
+                                                                                                                            img( src: branchImg(divId), id: divId+'img' )
+                                                                                                                        }
+                                                                                                                    }
+                                                                                                                    else
+                                                                                                                        img(src: dashImg)
+                                                                                                                    a( href: assetSubItemShowLink(assetSubItemL3.id), onclick: onclickHideAndSavePane() ) {
+                                                                                                                        yieldUnescaped( name(assetSubItemL3) )
+                                                                                                                    }
+                                                                                                                    yieldUnescaped( description(assetSubItemL3) )
+                                                                                                                    a(href: assetSubItemCreateWithParentLink(assetSubItemL3.id), onclick: onclickHideAndSavePane()) {
+                                                                                                                        img(src: addImg, alt: 'Add', title: 'Add Sub Item')
+                                                                                                                    }
+                                                                                                                } // li
+
+                                                                                                                if(assetSubItemL3.subItems) {
+                                                                                                                    div( id: divId, style: branchStyle(divId) ) {
+                                                                                                                        ul() {
+                                                                                                                            for(assetSubItemL4 in assetSubItemL3.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }) {
+                                                                                                                                li() {
+            //                                                                                                                         if(assetSubItemL4.subItems) {
+            //                                                                                                                             a( href: toggleBranch(nextDivId()) ) {
+            //                                                                                                                                 img( src: branchImg(divId), id: divId+'img' )
+            //                                                                                                                             }
+            //                                                                                                                         }
+            //                                                                                                                         else
+                                                                                                                                    img(src: dashImg)
+                                                                                                                                    a( href: assetSubItemShowLink(assetSubItemL4.id), onclick: onclickHideAndSavePane() ) {
+                                                                                                                                        yieldUnescaped( name(assetSubItemL4) )
+                                                                                                                                    }
+                                                                                                                                    yieldUnescaped( description(assetSubItemL4) )
+            //                                                                                                                         a(href: assetSubItemCreateWithParentLink(assetSubItemL4.id), onclick: onclickHideAndSavePane()) {
+            //                                                                                                                             img(src: addImg, alt: 'Add', title: 'Add Sub Item')
+            //                                                                                                                         }
+                                                                                                                                } // li
+
+                                                                                                                            } // assetSubItemL4
+                                                                                                                        } // ul
+                                                                                                                    } // div
+                                                                                                                } // if(assetSubItemL3.subItems)
+
+
+                                                                                                            } // assetSubItemL3
+                                                                                                        } // ul
+                                                                                                    } // div
+                                                                                                } // if(assetSubItemL2.subItems)
+
+                                                                                            } // assetSubItemL2
+                                                                                        } // ul
+                                                                                    } // div
+                                                                                } // if(assetSubItemL1.subItems)
+
+                                                                            } // assetSubItemL1
+                                                                        } // ul
+                                                                    } // div
+                                                                } // if(asset.assetSubItems)
+
+                                                            } // assets
+                                                        } // ul
+                                                    } // div
+                                                } // if(section.assets)
+
+                                            } //sections
+                                        } // ul
+                                    } // div
+                                } // if(site.sections)
+                            } // sites
+                        } // ul
+                    } // td
+                } // tr
+            } // table
+
+            div( class: 'buttons') {
+                span(class: 'button') {
+                    input( type: 'button', value: g.message(code: 'default.close.text'), onclick: onclickHideAndSavePane() )
+                }
+            }
+
+        } // mkp
+
+        def totalTime = (System.currentTimeMillis() - startedAt)/1000
+        log.debug "Total time to build asset tree: " + totalTime + "sec."
+        return sw.toString()
+
+    } // buildAssetTree
+
+    /** js calls */
+
+    def hrefShowPane() {
+        'javascript: showAssetTreePane(\"assetTreePane\", \"assetTreeLoadingImg' +'\", \"' + assetTreeActionUrl + '\");'
+    }
+
+    def onclickHideAndSavePane() {
+        'return hideAssetTreePane(\"assetTreePane\", \"assetTreeTable' + '\", \"' + saveAssetTreeStatusActionUrl + '\");'
+    }
+
+    def hrefHideAndSavePane() {
+        'javascript: hideAssetTreePane(\"assetTreePane\", \"assetTreeTable' + '\", \"' + saveAssetTreeStatusActionUrl + '\");'
+    }
+
+    def toggleBranch(divId) {
+        js.toggleWithImg(divId, divId + 'img', bulletTreeMinusImg, bulletTreePlusImg)
+    }
+
+    /** Links */
+
+    def siteShowLink(id) {
+        siteShowBaseLink + '/' + id
+    }
+
+    def siteEditLink(id) {
+        siteEditBaseLink + '/' + id
+    }
+
+    def sectionCreateLink(siteId) {
+        sectionCreateBaseLink + '?site.id=' + siteId
+    }
+
+    def sectionShowLink(id) {
+        sectionShowBaseLink + '/' + id
+    }
+
+    def sectionEditLink(id) {
+        sectionEditBaseLink + '/' + id
+    }
+
+    def assetCreateLink(sectionId) {
+        assetCreateBaseLink + '?section.id=' + sectionId
+    }
+
+    def assetShowLink(id) {
+        assetShowBaseLink + '/' + id
+    }
+
+    def assetEditLink(id) {
+        assetEditBaseLink + '/' + id
+    }
+
+    def assetCopyLink(id) {
+        assetCopyBaseLink + '?assetToCopy.id=' + id
+    }
+
+    def assetSubItemCreateLink(assetId) {
+        assetSubItemCreateBaseLink + '?asset.id=' + assetId
+    }
+
+    def assetSubItemCreateWithParentLink(parentItemId) {
+        assetSubItemCreateWithParentBaseLink + '?parentItem.id=' + parentItemId
+    }
+
+    def assetSubItemShowLink(id) {
+        assetSubItemShowBaseLink + '/' + id
+    }
+
+    def assetSubItemEditLink(id) {
+        assetSubItemEditBaseLink + '/' + id
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/AssignedGroupService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/AssignedGroupService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/AssignedGroupService.groovy	(revision 753)
@@ -0,0 +1,209 @@
+import org.hibernate.FetchMode as FM
+
+class AssignedGroupService {
+
+    boolean transactional = false
+
+    def authService
+
+    def delete(params) {
+        AssignedGroup.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.assignedGroupInstance && m.field)
+                    result.assignedGroupInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["AssignedGroup", params.id] ]
+                return result
+            }
+
+            result.assignedGroupInstance = AssignedGroup.get(params.id)
+
+            if(!result.assignedGroupInstance)
+                return fail(code:"default.not.found")
+
+            def taskModification = new TaskModification(person: authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(10),
+                                                    task: result.assignedGroupInstance.task)
+
+            if(!taskModification.save())
+                return fail(field:"taskModifications", code:"task.modifications.failedToSave")
+
+            try {
+                result.assignedGroupInstance.delete(flush:true)
+                return result //Success.
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                return fail(code:"default.delete.failure")
+            }
+
+        } //end withTransaction
+    } // end delete()
+
+    def edit(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["AssignedGroup", params.id] ]
+            return result
+        }
+
+        result.assignedGroupInstance = AssignedGroup.createCriteria().get {
+            idEq(params.id.toLong())
+            fetchMode("personGroup", FM.EAGER)
+            fetchMode("personGroup.persons", FM.EAGER)
+        }
+
+        if(!result.assignedGroupInstance)
+            return fail(code:"default.not.found")
+
+        result.personGroup = result.assignedGroupInstance.personGroup
+        result.personsInGroup = result.personGroup.persons.sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }
+
+        // Success.
+        return result
+    }
+
+    def update(params) {
+        AssignedGroup.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.assignedGroupInstance && m.field)
+                    result.assignedGroupInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["AssignedGroup", params.id] ]
+                return result
+            }
+
+            result.personGroup = PersonGroup.createCriteria().get {
+                idEq(params.personGroup.id.toLong())
+                fetchMode("persons", FM.EAGER)
+            }
+
+            // Prevent a null property reference.
+            if(!result.personGroup)
+                return fail(code:"personGroup.not.found")
+
+            result.personsInGroup = result.personGroup.persons.sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }
+
+            result.assignedGroupInstance = AssignedGroup.get(params.id)
+
+            if(!result.assignedGroupInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.assignedGroupInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            result.assignedGroupInstance.properties = params
+
+            if(result.assignedGroupInstance.hasErrors() || !result.assignedGroupInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person: authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(10),
+                                                    task: result.assignedGroupInstance.task)
+
+            if(!taskModification.save())
+                return fail(field:"taskModifications", code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end update()
+
+    def create(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["AssignedGroup", params.id] ]
+            return result
+        }
+
+        if(!params.task?.id)
+            fail(code:"assignedGroup.task.not.found")
+
+        result.assignedGroupInstance = new AssignedGroup()
+        result.assignedGroupInstance.properties = params
+
+        result.personGroup = PersonGroup.list().sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }[0] // Get the first result.
+        result.personsInGroup = result.personGroup.persons.sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }
+
+        // Success.
+        return result
+    }
+
+    def save(params) {
+        AssignedGroup.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.assignedGroupInstance && m.field)
+                    result.assignedGroupInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["AssignedGroup", params.id] ]
+                return result
+            }
+
+            result.personGroup = PersonGroup.createCriteria().get {
+                idEq(params.personGroup.id.toLong())
+                fetchMode("persons", FM.EAGER)
+            }
+
+            // Prevent a null property reference.
+            if(!result.personGroup)
+                return fail(code:"personGroup.not.found")
+
+            result.personsInGroup = result.personGroup.persons.sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }
+
+            result.assignedGroupInstance = new AssignedGroup()
+            result.assignedGroupInstance.properties = params
+
+            if(result.assignedGroupInstance.hasErrors() || !result.assignedGroupInstance.save())
+                return fail(code:"default.create.failure")
+
+            // Record a taskModification for everyone except "system".
+            if(authService.currentUser.id != 1) {
+                def taskModification = new TaskModification(person: authService.currentUser,
+                                                        taskModificationType: TaskModificationType.get(10),
+                                                        task: result.assignedGroupInstance.task)
+
+                if(!taskModification.save())
+                    return fail(field:"taskModifications", code:"task.modifications.failedToSave")
+            }
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    } // end save()
+
+    def personsInGroup(params) {
+        def result = [:]
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["PersonGroup", params.personGroup?.id] ]
+            return result
+        }
+
+        if(!params.personGroup?.id?.isLong())
+            return fail(code:"default.not.found")
+
+        result.personGroup = PersonGroup.createCriteria().get {
+            idEq(params.personGroup.id.toLong())
+            fetchMode("persons", FM.EAGER)
+        }
+
+        if(!result.personGroup)
+            return fail(code:"default.not.found")
+
+        result.personsInGroup = result.personGroup.persons.sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }
+
+        // Success.
+        return result
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/AssignedPersonService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/AssignedPersonService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/AssignedPersonService.groovy	(revision 753)
@@ -0,0 +1,191 @@
+class AssignedPersonService {
+
+    boolean transactional = false
+
+    def authService
+
+    def delete(params) {
+        AssignedPerson.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.assignedPersonInstance && m.field)
+                    result.assignedPersonInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["AssignedPerson", params.id] ]
+                return result
+            }
+
+            result.assignedPersonInstance = AssignedPerson.get(params.id)
+
+            if(!result.assignedPersonInstance)
+                return fail(code:"default.not.found")
+
+            def taskModification = new TaskModification(person: authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(11),
+                                                    task: result.assignedPersonInstance.task)
+
+            if(!taskModification.save())
+                return fail(field:"taskModifications", code:"task.modifications.failedToSave")
+
+            try {
+                result.assignedPersonInstance.delete(flush:true)
+                return result //Success.
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                return fail(code:"default.delete.failure")
+            }
+
+        } //end withTransaction
+    } // end delete()
+
+    def edit(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["AssignedPerson", params.id] ]
+            return result
+        }
+
+        result.assignedPersonInstance = AssignedPerson.get(params.id)
+
+        if(!result.assignedPersonInstance)
+            return fail(code:"default.not.found")
+
+        result.person = result.assignedPersonInstance.person
+        result.groupsForPerson = result.person.personGroups.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+
+        // Success.
+        return result
+    }
+
+    def update(params) {
+        AssignedPerson.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.assignedPersonInstance && m.field)
+                    result.assignedPersonInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["AssignedPerson", params.id] ]
+                return result
+            }
+
+            result.person = Person.get(params.person.id)
+
+            // Prevent a null property reference.
+            if(!result.person)
+                return fail(code:"person.not.found")
+
+            result.groupsForPerson = result.person.personGroups.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+
+            result.assignedPersonInstance = AssignedPerson.get(params.id)
+
+            if(!result.assignedPersonInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.assignedPersonInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            result.assignedPersonInstance.properties = params
+
+            if(result.assignedPersonInstance.hasErrors() || !result.assignedPersonInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person: authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(11),
+                                                    task: result.assignedPersonInstance.task)
+
+            if(!taskModification.save())
+                return fail(field:"taskModifications", code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end update()
+
+    def create(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["AssignedPerson", params.id] ]
+            return result
+        }
+
+        if(!params.task?.id)
+            fail(code:"assignedPerson.task.not.found")
+
+        result.assignedPersonInstance = new AssignedPerson()
+        result.assignedPersonInstance.properties = params
+
+        result.person = Person.list().sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }[0] // Get the first result.
+        result.groupsForPerson = result.person.personGroups.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+
+        // Success.
+        return result
+    }
+
+    def save(params) {
+        AssignedPerson.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.assignedPersonInstance && m.field)
+                    result.assignedPersonInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["AssignedPerson", params.id] ]
+                return result
+            }
+
+            result.person = Person.get(params.person.id)
+
+            // Prevent a null property reference.
+            if(!result.person)
+                return fail(code:"person.not.found")
+
+            result.groupsForPerson = result.person.personGroups?.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+
+            result.assignedPersonInstance = new AssignedPerson()
+            result.assignedPersonInstance.properties = params
+
+            if(result.assignedPersonInstance.hasErrors() || !result.assignedPersonInstance.save())
+                return fail(code:"default.create.failure")
+
+            // Record a taskModification for every one except "system".
+            if(authService.currentUser.id != 1) {
+                def taskModification = new TaskModification(person: authService.currentUser,
+                                                        taskModificationType: TaskModificationType.get(11),
+                                                        task: result.assignedPersonInstance.task)
+
+                if(!taskModification.save())
+                    return fail(field:"taskModifications", code:"task.modifications.failedToSave")
+            }
+
+            // success
+            return result
+
+        } //end withTransaction
+    } // end save()
+
+    def groupsForPerson(params) {
+        def result = [:]
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["Person", params.person?.id] ]
+            return result
+        }
+
+        result.person = Person.get(params.person?.id)
+
+        if(!result.person)
+            return fail(code:"default.not.found")
+
+        result.groupsForPerson = result.person.personGroups.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+
+        // Success.
+        return result
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/AuthService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/AuthService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/AuthService.groovy	(revision 753)
@@ -0,0 +1,49 @@
+/**
+ * Provides a service class with some methods that integrate the Person domain class and Acegi security.
+ *
+ */
+class AuthService {
+
+    boolean transactional = false
+
+    def authenticateService
+
+    /**
+    * Get the current user in a safe way to avoid a null userDomain.
+    * @returns The current user or the 'system' person (Person #1) if userDomain() is not active.
+    */
+    def getCurrentUser() {
+        if(authenticateService.userDomain()) {
+            return Person.get(authenticateService.userDomain().id)
+        }
+        else {
+            log.warn "userDomain not active, attempting to return Person #1."
+            return Person.get(1)
+        }
+    }
+
+    /**
+    * Convenience wrapper around authenticateService.encodePassword().
+    * @param passClearText The clear text password to encode.
+    * @returns The encoded password.
+    */
+    def encodePassword(passClearText) {
+        authenticateService.encodePassword(passClearText)
+    }
+
+    /**
+    * Generate a random password.
+    * @returns The generated password.
+    */
+    def getRandomPassword() {
+        def passwd = ""
+        def pool = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
+        def rand = new Random(System.currentTimeMillis())
+
+        for(i in 0..10)
+            passwd += pool[rand.nextInt(pool.length())]
+
+        return passwd
+    }
+
+}
Index: branches/features/taskProcedureRework/grails-app/services/ContactService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/ContactService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/ContactService.groovy	(revision 753)
@@ -0,0 +1,99 @@
+/**
+ * Provides a service class with methods to interact with the Contact domain class.
+ * Contact stores contact details for various objects in the database.
+ */
+class ContactService {
+
+    boolean transactional = false
+
+    def delete(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["Contact", params.id] ]
+            return result
+        }
+
+        result.contactInstance = Contact.get(params.id)
+
+        if(!result.contactInstance)
+            return fail(code:"default.not.found")
+
+        result.ownerInstance = getOwner(result.contactInstance)
+
+        try {
+            result.contactInstance.delete(flush:true)
+            return result //Success.
+        }
+        catch(org.springframework.dao.DataIntegrityViolationException e) {
+            return fail(code:"default.delete.failure")
+        }
+
+    }
+
+    def create(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["Contact", params.id] ]
+            return result
+        }
+
+        result.ownerInstance = getOwner(params)
+        if(!result.ownerInstance)
+            return fail(code:"contact.owner.not.found")
+
+        result.contactInstance = new Contact()
+        result.contactInstance.properties = params
+
+        // success
+        return result
+    }
+
+    def save(params) {
+        def result = [:]
+        def fail = { Map m ->
+            if(result.contactInstance && m.field)
+                result.contactInstance.errors.rejectValue(m.field, m.code)
+            result.error = [ code: m.code, args: ["Contact", params.id] ]
+            return result
+        }
+
+        result.ownerInstance = getOwner(params)
+        if(!result.ownerInstance)
+            return fail(code:"contact.owner.not.found")
+
+        result.contactInstance = new Contact(params)
+
+        if(result.contactInstance.hasErrors() || !result.contactInstance.save(flush: true))
+            return fail(code:"default.create.failure")
+
+        // success
+        return result
+    }
+
+    private getOwner(Map params) {
+        def ownerInstance
+
+        if(params.supplier?.id)
+            return ownerInstance = Supplier.get(params.supplier.id)
+        if(params.person?.id)
+            return ownerInstance = Person.get(params.person.id)
+        if(params.site?.id)
+            return ownerInstance = Site.get(params.site.id)
+
+        return false
+    }
+
+    private getOwner(Object object) {
+        def ownerInstance
+
+        if(object.supplier)
+            return ownerInstance = object.supplier
+        if(object.person)
+            return ownerInstance = object.person
+        if(object.site)
+            return ownerInstance = object.site
+
+        return false
+    }
+
+} // end of class
Index: branches/features/taskProcedureRework/grails-app/services/CreateBulkDataService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/CreateBulkDataService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/CreateBulkDataService.groovy	(revision 753)
@@ -0,0 +1,391 @@
+import grails.util.GrailsUtil
+
+/**
+* Provides a data service to create a large volume of test data for load testing.
+*/
+class  CreateBulkDataService {
+
+    boolean transactional = false
+
+    def authService
+    def taskService
+    def dateUtilService
+    def appConfigService
+    def createDataService
+    def searchableService
+    def assignedGroupService
+    def assignedPersonService
+    def inventoryItemService
+
+    def sessionFactory
+    def grailsApplication
+    def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP
+
+    def startTime
+    def lastBatchStarted
+
+/*******************************************
+Start of Group methods.
+Generally use these methods to create data.
+*******************************************/
+
+    /**
+    * Make a run of data creation.
+    */
+    def createAll() {
+        def result = [:]
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: m.args ]
+            return result
+        }
+
+        if(GrailsUtil.environment != "development")
+            return fail(code: 'default.not.development.environment.failure')
+
+        createDataService.stopSearchableIndex()
+
+        log.info "Creating BULK data..."
+
+        // Person and Utils
+        log.info "Creating persons..."
+        createBulkTestPersons()
+//         createBulkTestSites()
+//         createBulkTestDepartments()
+//         createBulkTestSuppliers()
+
+        // Assets
+//         createBulkTestTaskProcedure()
+//         createBulkTestMaintenanceActions()
+//         createBulkTestSections()
+//         createBulkTestAssets()
+//         createBulkTestAssetExtenedAttributes()
+//         createBulkTestAssetSubItems()
+//         createBulkTestAssetSubItemExtenedAttributes()
+
+        // Inventory
+        log.info "Creating inventory..."
+//         createBulkTestInventoryStores()  /// @todo: Perhaps a 'createQuickStartData' method?
+        createBulkTestInventoryLocations()
+//         createBulkTestInventoryGroups() /// @todo: Perhaps a 'createQuickStartData' method?
+        createBulkTestInventoryItems()
+
+        // Tasks
+        log.info "Creating tasks..."
+        createBulkTestTasks()
+//         createBulkTestEntries()
+//         createBulkTestAssignedGroups()
+//         createBulkTestAssignedPersons()
+//         createBulkTestTaskRecurringSchedules()
+
+        log.info "Creating BULK data...complete."
+
+        createDataService.startSearchableIndex()
+
+        return result
+
+    } // create()
+
+    /**
+    * Make a run of inventory data creation.
+    */
+    def createBulkInventoryTestData() {
+        def result = [:]
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: m.args ]
+            return result
+        }
+
+        if(GrailsUtil.environment != "development")
+            return fail(code: 'default.not.development.environment.failure')
+
+        createDataService.stopSearchableIndex()
+
+        log.info "Creating BULK data..."
+
+        // Inventory
+        log.info "Creating inventory..."
+//         createBulkTestInventoryStores()  /// @todo: Perhaps a 'createQuickStartData' method?
+        createBulkTestInventoryLocations()
+//         createBulkTestInventoryGroups() /// @todo: Perhaps a 'createQuickStartData' method?
+        createBulkTestInventoryItems()
+
+        log.info "Creating BULK data...complete."
+
+        createDataService.startSearchableIndex()
+
+        return result
+
+    } // createBulkInventoryTestData()
+
+/******************
+Start of Person
+*******************/
+
+    def createBulkTestPersons() {
+        //Person
+        def passClearText = "pass"
+        def passwordEncoded = authService.encodePassword(passClearText)
+        def personInstance
+
+        def start = Person.count() + 1
+        def end = start + 100
+
+        def range = start..end
+
+        def loginName = "BtLoginName"
+        String btLoginName
+        def firstName = "BtFirstName"
+        String btFirstName
+        def lastName = "BtLastName"
+
+        def authority2 = Authority.get(2)
+        def authority3 = Authority.get(3)
+        def personGroup1 = PersonGroup.get(1)
+        def personGroup2 = PersonGroup.get(2)
+        def personGroup3 = PersonGroup.get(3)
+        def personGroup4 = PersonGroup.get(4)
+        def personGroup5 = PersonGroup.get(5)
+
+        range.each() {
+
+            btLoginName = loginName + it
+            btFirstName = firstName + it
+
+            personInstance = new Person(loginName: btLoginName,
+                                        firstName: btFirstName,
+                                        lastName: lastName,
+                                        pass: passClearText,
+                                        password: passwordEncoded)
+            saveAndTest(personInstance)
+            personInstance.addToAuthorities(authority2)
+            personInstance.addToAuthorities(authority3)
+            personInstance.addToPersonGroups(personGroup1)
+            personInstance.addToPersonGroups(personGroup2)
+            personInstance.addToPersonGroups(personGroup3)
+            personInstance.addToPersonGroups(personGroup4)
+            personInstance.addToPersonGroups(personGroup5)
+
+        }
+
+    } // createBulkTestPersons()
+
+/*********************
+START OF TASK
+*********************/
+
+    def createBulkTestTasks() {
+
+        def taskResult
+        def p = [:]
+
+        def start = Task.count() + 1
+        def end = start + 10000
+
+        def range = start..end
+
+
+        def taskGroup1 = TaskGroup.get(1)
+        def taskPriority2 = TaskPriority.get(2)
+        def taskType3 = TaskType.get(3)
+        def leadPerson2 = Person.get(2)
+
+        def description = "Bulk test data "
+        String btDescription
+        def comment1 = "Has been noted as problematic, try recalibrating."
+        def today = dateUtilService.today
+
+        startTime = System.currentTimeMillis()
+        lastBatchStarted = startTime
+
+        range.each() {
+
+            if(it % 100 == 0) {
+                logStatus("Creating task #" + it)
+                cleanUpGorm()
+            }
+
+            btDescription = description + it
+
+            //Task #1
+            p = [taskGroup: taskGroup1,
+                    taskPriority: taskPriority2,
+                    taskType: taskType3,
+                    leadPerson: leadPerson2,
+                    description: btDescription,
+                    comment: comment1,
+                    targetStartDate: today]
+
+            taskResult = taskService.save(p)
+        }
+
+    } // createBulkTestTasks()
+
+    def createBulkTestEntries() {
+
+        def entryResult
+        def p = [:]
+
+        def range = 1..10
+        def task1 = Task.get(1)
+        def entryType1 = EntryType.get(1)
+        def comment1 = "This is a bulk test entry."
+        def durationMinute1 = 20
+
+        range.each() {
+
+            p = [task: task1,
+                    entryType: entryType1,
+                    comment: comment1,
+                    durationMinute: durationMinute1]
+
+            entryResult = taskService.saveEntry(p)
+
+        }
+
+    } // createBulkTestEntries()
+
+
+/**************************
+START OF INVENTORY
+**************************/
+
+    def createBulkTestInventoryLocations() {
+
+        def inventoryLocationResult
+        def p = [:]
+
+        def start = InventoryLocation.count() + 1
+        def end = start + 50
+
+        def range = start..end
+
+
+        def inventoryStore1 = InventoryStore.read(1)
+
+        def name = "Bulk test location "
+        def btName = ''
+
+        startTime = System.currentTimeMillis()
+        lastBatchStarted = startTime
+
+        range.each() {
+
+            if(it % 25 == 0) {
+                logStatus("Creating inventory location #" + it)
+                cleanUpGorm()
+            }
+
+            btName = name + it
+
+            p = [inventoryStore: inventoryStore1,
+                    name: btName]
+
+            inventoryLocationResult = new InventoryLocation(p).save()
+        } // each()
+
+    } // createBulkTestInventoryLocations()
+
+    def createBulkTestInventoryItems() {
+
+        def inventoryItemInstance
+        def p = [:]
+
+        def pictureResource = grailsApplication.mainContext.getResource('images/logo.png')
+
+        def start = InventoryItem.count() + 1
+        def end = start + 250
+
+        def range = start..end
+
+        def inventoryLocation
+        def inventoryLocationIndex = 0
+        def inventoryLocationList = InventoryLocation.findAll()
+        def unitOfMeasure2 = UnitOfMeasure.read(2)
+        def inventoryType1 = InventoryType.read(1)
+        def inventoryGroup1 = InventoryGroup.read(1)
+
+        def name = "Bulk test inventory item "
+        def btName = ''
+
+        startTime = System.currentTimeMillis()
+        lastBatchStarted = startTime
+
+        range.each() {
+
+            if(it % 50 == 0) {
+                logStatus("Creating inventory item #" + it)
+                cleanUpGorm()
+            }
+
+            // Spread the inventoryItems across all available locations.
+            if(inventoryLocationIndex < inventoryLocationList.size()) {
+                inventoryLocation = inventoryLocationList[inventoryLocationIndex]
+            }
+            else {
+                inventoryLocationIndex = 0
+                inventoryLocation = inventoryLocationList[inventoryLocationIndex]
+            }
+            inventoryLocationIndex++
+
+            // Change the name for each inventoryItem.
+            btName = name + it
+
+            p = [inventoryGroup: inventoryGroup1,
+                    inventoryType: inventoryType1,
+                    unitOfMeasure: unitOfMeasure2,
+                    inventoryLocation: inventoryLocation,
+                    name: btName,
+                    description: "Bulk test data",
+                    unitsInStock: 2,
+                    reorderPoint: 0]
+
+            inventoryItemInstance = new InventoryItem(p)
+            saveAndTest(inventoryItemInstance)
+
+            def pictureResult = inventoryItemService.savePicture(inventoryItemInstance, pictureResource)
+
+            if(pictureResult.error)
+                log.error pictureResult.error
+        } // each()
+
+    } // createBulkTestInventoryItems()
+
+    /**
+    * This cleans up the hibernate session and a grails map.
+    * For more info see: http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/
+    * The hibernate session flush is normal for hibernate.
+    * The map is apparently used by grails for domain object validation errors.
+    * A starting point for clean up is every 100 objects.
+    */
+    def cleanUpGorm() {
+        def session = sessionFactory.currentSession
+        session.flush()
+        session.clear()
+        propertyInstanceMap.get().clear()
+    }
+
+    def logStatus(String message) {
+        def batchEnded = System.currentTimeMillis()
+        def seconds = (batchEnded-lastBatchStarted)/1000
+        def total = (batchEnded-startTime)/1000
+        log.info "${message}, last: ${seconds}s, total: ${total}s"
+        lastBatchStarted = batchEnded
+    }
+
+
+/****************************************
+Call this function instead of .save()
+*****************************************/
+    private boolean saveAndTest(object) {
+        if(!object.save()) {
+//             BulkTestDataSuccessful = false
+            log.error "'${object}' failed to save!"
+            log.error object.errors
+            return false
+        }
+        return true
+    }
+
+} // end class.
Index: branches/features/taskProcedureRework/grails-app/services/CreateDataService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/CreateDataService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/CreateDataService.groovy	(revision 753)
@@ -0,0 +1,1742 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
+/**
+* Provides a data service to create base and demo data.
+* Beware that most, if not all, base data is referenced by "Id" throughout the program.
+* This allows changing the text of the 'name' property to something of the same meaning.
+* But be sure to maintain the correct Id during creation, indicated by #1, #2 etc.
+*/
+class  CreateDataService {
+
+    boolean transactional = false
+
+    def authService
+    def taskService
+    def dateUtilService
+    def appConfigService
+    def searchableService
+    def inventoryItemService
+    def assignedGroupService
+    def assignedPersonService
+
+    def grailsApplication
+
+/*******************************************
+Start of Group methods.
+Generally use these methods to create data.
+*******************************************/
+
+    /**
+    * Always call this at startup to ensure that we have admin access
+    * and that the system pseudo person is available.
+    */
+    def ensureSystemAndAdminAccess() {
+        if(!Authority.findByAuthority("ROLE_AppAdmin") ) {
+            log.warn "ROLE_AppAdmin not found, calling createAdminAuthority()."
+            createAdminAuthority()
+        }
+        if(!Person.findByLoginName("system") ) {
+            log.warn "LoginName 'system' not found, calling createSystemPerson()."
+            createSystemPerson()
+        }
+        if(!Person.findByLoginName("admin") ) {
+            log.warn "LoginName 'admin' not found, calling createAdminPerson()."
+            createAdminPerson()
+        }
+    }
+
+    /**
+    * Create the base data required for the application to function.
+    */
+    def createBaseData() {
+
+        if(appConfigService.exists("baseDataCreated")) {
+            log.info "Base data previously created."
+            return false
+        }
+
+        log.info "Creating base data."
+
+        // Person and Utils
+        createBaseAuthorities()
+        createBasePersonGroupTypes()
+        createBasePersonGroups()
+        createBaseDefinitions()
+        createBaseUnitsOfMeasure()
+        createBasePeriods()
+        createBaseSupplierTypes()
+        createBaseAddressTypes()
+        createBaseContactTypes()
+        createBaseMaintenancePolicies()
+        createBaseInventoryItemPurchaseTypes()
+
+        // Assets
+        createBaseExtenededAttributeTypes()
+
+        // Inventory
+        createBaseInventoryTypes()
+        createBaseInventoryMovementTypes()
+
+        // Tasks
+        createBaseTaskGroups()
+        createBaseTaskStatus()
+        createBaseTaskPriorities()
+        createBaseTaskBudgetStatus()
+        createBaseTaskTypes()
+        createBaseTaskModificationTypes()
+        createBaseEntryTypes()
+
+        // Record that data has been created.
+        appConfigService.set("baseDataCreated")
+    }
+
+    /**
+    * Create demo data for some example sites.
+    */
+    def createDemoData() {
+
+        if(!appConfigService.exists("baseDataCreated")) {
+            log.error "Demo data cannot be created until base data has been created."
+            return false
+        }
+
+        if(appConfigService.exists("demoDataCreated")) {
+            log.error "Demo data has already been created, will NOT recreate."
+            return false
+        }
+
+        if(appConfigService.exists("demoDataCreationDisabled")) {
+            log.error "Demo data creation has been disabled, will NOT create."
+            return false
+        }
+
+        log.info "Creating demo data..."
+
+        // Person and Utils
+        createDemoSites()
+        createDemoDepartments()
+        createDemoSuppliers()
+        createDemoProductionReference()
+        createDemoPurchasingGroups()  /// @todo: Perhaps a 'createQuickStartData' method?
+        createDemoCostCodes()
+        createDemoPersons()
+
+        // Assets
+        createDemoSections()
+        createDemoAssetTree()
+        createDemoAssetExtendedAttributes()
+        createDemoAssetSubItemExtendedAttributes()
+
+        // Inventory
+        createDemoInventoryStores()  /// @todo: Perhaps a 'createQuickStartData' method?
+        createDemoInventoryLocations()
+        createDemoInventoryGroups() /// @todo: Perhaps a 'createQuickStartData' method?
+        createDemoInventoryItems()
+
+        // Tasks
+        createDemoTasks()
+        createDemoEntries()
+        createDemoAssignedGroups()
+        createDemoAssignedPersons()
+        createDemoTaskProcedure()
+        createDemoMaintenanceActions()
+        createDemoTaskRecurringSchedules()
+
+        // Record that data has been created.
+        appConfigService.set("demoDataCreated")
+    }
+
+/******************
+Start of Person
+*******************/
+
+    def createAdminAuthority() {
+        def authInstance
+
+        // Authority #1
+        authInstance = new Authority(description:"Application Admin, not required for daily use! \
+                                                                                Grants full admin access to the application.",
+                                        authority:"ROLE_AppAdmin")
+        saveAndTest(authInstance)
+    }
+
+    def createBaseAuthorities() {
+
+        def authInstance
+
+        // Authority #2
+        authInstance = new Authority(description:"Business Manager, grants full management access.",
+                                                            authority:"ROLE_Manager")
+        saveAndTest(authInstance)
+
+        // Authority #3
+        authInstance = new Authority(description:"Application User, all application users need this base role \
+                                                                                    to allow login.",
+                                                            authority:"ROLE_AppUser")
+        saveAndTest(authInstance)
+
+        // Authority #4
+        authInstance = new Authority(description:"Task Manager",
+                                                            authority:"ROLE_TaskManager")
+        saveAndTest(authInstance)
+
+        // Authority #5
+        authInstance = new Authority(description:"Task User",
+                                                            authority:"ROLE_TaskUser")
+        saveAndTest(authInstance)
+
+        // Authority #6
+        authInstance = new Authority(description:"Inventory Manager",
+                                                            authority:"ROLE_InventoryManager")
+        saveAndTest(authInstance)
+
+        // Authority #7
+        authInstance = new Authority(description:"Inventory User",
+                                                            authority:"ROLE_InventoryUser")
+        saveAndTest(authInstance)
+
+        // Authority #8
+        authInstance = new Authority(description:"Asset Manager",
+                                                            authority:"ROLE_AssetManager")
+        saveAndTest(authInstance)
+
+        // Authority #9
+        authInstance = new Authority(description:"Asset User",
+                                                            authority:"ROLE_AssetUser")
+        saveAndTest(authInstance)
+
+        // Authority #10
+        authInstance = new Authority(description:"Production Manager",
+                                                            authority:"ROLE_ProductionManager")
+        saveAndTest(authInstance)
+
+        // Authority #11
+        authInstance = new Authority(description:"Production User",
+                                                            authority:"ROLE_ProductionUser")
+        saveAndTest(authInstance)
+    }
+
+    void createBasePersonGroupTypes() {
+
+        //PersonGroupType.
+        def personGroupTypeInstance
+        personGroupTypeInstance = new PersonGroupType(name:"Team")
+        saveAndTest(personGroupTypeInstance)
+        personGroupTypeInstance = new PersonGroupType(name:"Contractor")
+        saveAndTest(personGroupTypeInstance)
+        personGroupTypeInstance = new PersonGroupType(name:"Project Team")
+        saveAndTest(personGroupTypeInstance)
+    }
+
+    void createBasePersonGroups() {
+
+        //PersonGroup
+        def personGroupInstance
+        personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(1),
+                                                                                name:"Electrical - General")
+        saveAndTest(personGroupInstance)
+        personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(1),
+                                                                                name:"Mechanical - General")
+        saveAndTest(personGroupInstance)
+        personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(1),
+                                                                                name:"Production")
+        saveAndTest(personGroupInstance)
+        personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(2),
+                                                                                name:"AirCon Contractor")
+        saveAndTest(personGroupInstance)
+        personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(3),
+                                                                                name:"gnuMims")
+        saveAndTest(personGroupInstance)
+    }
+
+    def createSystemPerson() {
+        //Person
+        def passClearText = "pass"
+        def passwordEncoded = authService.encodePassword(passClearText)
+        def personInstance
+
+        //Person #1
+        personInstance = new Person(loginName:"system",
+                                    firstName:"gnuMims",
+                                    lastName:"System",
+                                    description:'''This is a pseudo person that the application uses to insert data. DO NOT
+                                                        assign login authorities or change the details of this person.''',
+                                    pass:passClearText,
+                                    password:passwordEncoded)
+        saveAndTest(personInstance)
+    }
+
+    def createAdminPerson() {
+        //Person
+        def passClearText = "pass"
+        def passwordEncoded = authService.encodePassword(passClearText)
+        def personInstance
+
+        //Person #2
+        personInstance = new Person(loginName:"admin",
+                                    firstName:"Admin",
+                                    lastName:"Powers",
+                                    description:'''Every time the application starts it ensures that the 'admin' login name is available.
+                                                        DO update the password and other details but keep the login name as 'admin'. ''',
+                                    pass:passClearText,
+                                    password:passwordEncoded)
+        saveAndTest(personInstance)
+        personInstance.addToAuthorities(Authority.get(1))
+    }
+
+    def createBasePersons() {
+    }
+
+    def createDemoPersons() {
+        //Person
+        def passClearText = "pass"
+        def passwordEncoded = authService.encodePassword(passClearText)
+        def personInstance
+
+        //Person #1 is system.
+        //Person #2 is admin.
+
+        //Person #3
+        personInstance = new Person(loginName:"manager",
+                                    firstName:"Demo",
+                                    lastName:"Manager",
+                                    pass:passClearText,
+                                    password:passwordEncoded)
+        saveAndTest(personInstance)
+        personInstance.addToAuthorities(Authority.get(2)) // ROLE_Manager.
+        personInstance.addToAuthorities(Authority.get(3)) // ROLE_AppUser.
+        personInstance.addToPersonGroups(PersonGroup.get(1))
+        personInstance.addToPurchasingGroups(PurchasingGroup.get(1))
+        personInstance.addToPurchasingGroups(PurchasingGroup.get(2))
+
+        //Person #4
+        personInstance = new Person(loginName:"user",
+                                    firstName:"Demo",
+                                    lastName:"User",
+                                    pass:passClearText,
+                                    password:passwordEncoded)
+        saveAndTest(personInstance)
+        personInstance.addToAuthorities(Authority.get(3)) // ROLE_AppUser.
+        personInstance.addToAuthorities(Authority.get(5)) // ROLE_TaskManager.
+        personInstance.addToAuthorities(Authority.get(7)) // ROLE_InventoryUser.
+        personInstance.addToAuthorities(Authority.get(9)) // ROLE_AssetUser.
+        personInstance.addToPersonGroups(PersonGroup.get(1))
+
+        //Person #5
+        personInstance = new Person(loginName:"craig",
+                                    firstName:"Craig",
+                                    lastName:"SuperSparky",
+                                    pass:passClearText,
+                                    password:passwordEncoded)
+        saveAndTest(personInstance)
+        personInstance.addToAuthorities(Authority.get(3))
+        personInstance.addToAuthorities(Authority.get(5))
+        personInstance.addToAuthorities(Authority.get(7))
+        personInstance.addToAuthorities(Authority.get(9))
+        personInstance.addToPersonGroups(PersonGroup.get(1))
+
+        //Person #6
+        personInstance = new Person(loginName:"john",
+                                    firstName:"John",
+                                    lastName:"SuperFitter",
+                                    pass:passClearText,
+                                    password:passwordEncoded)
+        saveAndTest(personInstance)
+        personInstance.addToAuthorities(Authority.get(3))
+        personInstance.addToAuthorities(Authority.get(5))
+        personInstance.addToAuthorities(Authority.get(7))
+        personInstance.addToAuthorities(Authority.get(9))
+        personInstance.addToPersonGroups(PersonGroup.get(2))
+
+        //Person #7
+        personInstance = new Person(loginName:"production manager",
+                                    firstName:"Production",
+                                    lastName:"Manager",
+                                    pass:passClearText,
+                                    password:passwordEncoded)
+        saveAndTest(personInstance)
+        personInstance.addToAuthorities(Authority.get(3)) // ROLE_AppUser.
+        personInstance.addToAuthorities(Authority.get(10)) // ROLE_ProductionManager.
+        personInstance.addToPersonGroups(PersonGroup.get(3))
+
+        //Person #8
+        personInstance = new Person(loginName:"production",
+                                    firstName:"Production",
+                                    lastName:"User",
+                                    pass:passClearText,
+                                    password:passwordEncoded)
+        saveAndTest(personInstance)
+        personInstance.addToAuthorities(Authority.get(3)) // ROLE_AppUser.
+        personInstance.addToAuthorities(Authority.get(11)) // ROLE_ProductionUser.
+        personInstance.addToPersonGroups(PersonGroup.get(3))
+
+        //Person #9
+        personInstance = new Person(loginName:"testmanager",
+                                    firstName:"Test",
+                                    lastName:"Manager",
+                                    pass:passClearText,
+                                    password:passwordEncoded)
+        saveAndTest(personInstance)
+        personInstance.addToAuthorities(Authority.get(3)) // ROLE_AppUser.
+        personInstance.addToAuthorities(Authority.get(4)) // ROLE_TaskManager.
+        personInstance.addToAuthorities(Authority.get(6)) // ROLE_InventoryManager.
+        personInstance.addToAuthorities(Authority.get(8)) // ROLE_AssetManager.
+        personInstance.addToPersonGroups(PersonGroup.get(3))
+    }
+
+/***********************
+START OF UTILITIES
+***********************/
+
+    //These can redefined by the site at deployment time.
+    /// @todo: build an admin view so that only the value (definition) can be changed.
+    def createBaseDefinitions() {
+        appConfigService.set("Department Definition", "A department as recongised by accounting.")
+        appConfigService.set("Site Definition", "The plant, work or production site.")
+        appConfigService.set("Section Definition", "A logical grouping of assets, which may be an area, system or process \
+                                            as determined by design.")
+        appConfigService.set("Asset Definition",
+                                            "The complete asset as it is known on the site. \
+                                            Often purchased as a whole with the primary purpose of returning value by performing a function. \
+                                            An asset is made up of 1 or more sub assets and performs a complete function as specified by the designer.")
+        appConfigService.set("Asset Sub Item 1 Name",
+                                            "Sub Asset")
+        appConfigService.set("Asset Sub Item 1 Definition",
+                                            "A machine that performs part of a complete asset's function and often has a model number.")
+        appConfigService.set("Asset Sub Item 2 Name",
+                                            "Functional Assembly")
+        appConfigService.set("Asset Sub Item 2 Definition",
+                                            "Functional Assemblies are taken from the designer's functional list for the sub asset and are made up of sub \
+                                            assemblies that together perform that function.")
+        appConfigService.set("Asset Sub Item 3 Name",
+                                            "Sub Assembly Group")
+        appConfigService.set("Asset Sub Item 3 Definition",
+                                            "Group or type of part.")
+        appConfigService.set("Asset Sub Item 4 Name",
+                                            "Component Item")
+        appConfigService.set("Asset Sub Item 4 Definition",
+                                            "The smallest part that would be analysed for failure.")
+    }
+
+    def createDemoSites() {
+        //Site
+        def siteInstance
+
+        siteInstance = new Site(name: "CSM",
+                                                    description: "Creek Side Mill")
+        saveAndTest(siteInstance)
+
+        siteInstance = new Site(name: "Jasper Street Depot",
+                                                    description: "Storage depot on Jasper Street.")
+        saveAndTest(siteInstance)
+
+        siteInstance = new Site(name: "River Press",
+                                                    description: "Printing press site")
+        saveAndTest(siteInstance)
+    }
+
+    def createDemoDepartments() {
+
+        //Department
+        def departmentInstance
+
+        //Department #1
+        departmentInstance = new Department(name: "Print Centre",
+                                                                                description: "Printing Department",
+                                                                                site: Site.get(1))
+        saveAndTest(departmentInstance)
+
+        //Department #2
+        departmentInstance = new Department(name: "Pulp Mill",
+                                                                                description: "Business Department",
+                                                                                site: Site.get(2))
+        saveAndTest(departmentInstance)
+    }
+
+    def createBaseUnitsOfMeasure() {
+
+        //UnitOfMeasure
+        def unitOfMeasureInstance
+
+        //UnitOfMeasure #1
+        unitOfMeasureInstance = new UnitOfMeasure(name: "each")
+        saveAndTest(unitOfMeasureInstance)
+
+        //UnitOfMeasure #2
+        unitOfMeasureInstance = new UnitOfMeasure(name: "meter(s)")
+        saveAndTest(unitOfMeasureInstance)
+
+        //UnitOfMeasure #3
+        unitOfMeasureInstance = new UnitOfMeasure(name: "box(es)")
+        saveAndTest(unitOfMeasureInstance)
+
+        //UnitOfMeasure #4
+        unitOfMeasureInstance = new UnitOfMeasure(name: "litre(s)")
+        saveAndTest(unitOfMeasureInstance)
+
+        //UnitOfMeasure #5
+        unitOfMeasureInstance = new UnitOfMeasure(name: "kilogram(s)")
+        saveAndTest(unitOfMeasureInstance)
+
+        //UnitOfMeasure #6
+        unitOfMeasureInstance = new UnitOfMeasure(name: "gram(s)")
+        saveAndTest(unitOfMeasureInstance)
+    }
+
+    def createBasePeriods() {
+
+        //Period
+        def periodInstance
+
+        //Period #1
+        periodInstance = new Period(period: "Day(s)")
+        saveAndTest(periodInstance)
+
+        //Period #2
+        periodInstance = new Period(period: "Week(s)")
+        saveAndTest(periodInstance)
+
+        //Period #3
+        periodInstance = new Period(period: "Month(s)")
+        saveAndTest(periodInstance)
+
+        //Period #4
+        periodInstance = new Period(period: "Year(s)")
+        saveAndTest(periodInstance)
+    }
+
+    def createBaseSupplierTypes() {
+
+        // SupplierType
+        def supplierTypeInstance
+
+        // SupplierType #1
+        supplierTypeInstance = new SupplierType(name: "Unknown",
+                                                                    description: "Unknown supplier type")
+        saveAndTest(supplierTypeInstance)
+
+        // SupplierType #2
+        supplierTypeInstance = new SupplierType(name: "OEM",
+                                                                    description: "Original equipment supplier")
+        saveAndTest(supplierTypeInstance)
+
+        // SupplierType #3
+        supplierTypeInstance = new SupplierType(name: "Local",
+                                                                    description: "Local supplier")
+        saveAndTest(supplierTypeInstance)
+    }
+
+    def createBaseAddressTypes() {
+
+        // AddressType
+        def addressTypeInstance
+
+        // AddressType #1
+        addressTypeInstance = new AddressType(name: "Postal",
+                                                                                description: "A postal address.")
+        saveAndTest(addressTypeInstance)
+
+        // AddressType #2
+        addressTypeInstance = new AddressType(name: "Physical",
+                                                                                description: "A physical address.")
+        saveAndTest(addressTypeInstance)
+
+        // AddressType #3
+        addressTypeInstance = new AddressType(name: "Postal & Physical",
+                                                                                description: "An address that is both the postal and physical address.")
+        saveAndTest(addressTypeInstance)
+
+        // AddressType #4
+        addressTypeInstance = new AddressType(name: "Invoice",
+                                                                                description: "An address to send invoices to.")
+        saveAndTest(addressTypeInstance)
+
+        // AddressType #5
+        addressTypeInstance = new AddressType(name: "Delivery",
+                                                                                description: "An address to send deliveries to.")
+        saveAndTest(addressTypeInstance)
+    }
+
+    def createBaseContactTypes() {
+
+        // ContactType
+        def contactTypeInstance
+
+        // ContactType #1
+        contactTypeInstance = new ContactType(name: "Email",
+                                                                                description: "Email address.")
+        saveAndTest(contactTypeInstance)
+
+        // ContactType #2
+        contactTypeInstance = new ContactType(name: "Alternate Email",
+                                                                                description: "Alternate email address.")
+        saveAndTest(contactTypeInstance)
+
+        // ContactType #3
+        contactTypeInstance = new ContactType(name: "Mobile",
+                                                                                description: "Modile phone number.")
+        saveAndTest(contactTypeInstance)
+
+        // ContactType #4
+        contactTypeInstance = new ContactType(name: "Work Phone",
+                                                                                description: "Work phone number.")
+        saveAndTest(contactTypeInstance)
+
+        // ContactType #5
+        contactTypeInstance = new ContactType(name: "Home Phone",
+                                                                                description: "Home phone number.")
+        saveAndTest(contactTypeInstance)
+
+        // ContactType #6
+        contactTypeInstance = new ContactType(name: "Work Fax",
+                                                                                description: "Work fax number.")
+        saveAndTest(contactTypeInstance)
+
+        // ContactType #7
+        contactTypeInstance = new ContactType(name: "Home Fax",
+                                                                                description: "Home fax number.")
+        saveAndTest(contactTypeInstance)
+
+        // ContactType #8
+        contactTypeInstance = new ContactType(name: "Web Site",
+                                                                                description: "Web site address.")
+        saveAndTest(contactTypeInstance)
+
+        // ContactType #9
+        contactTypeInstance = new ContactType(name: "Person",
+                                                                                description: "Contact person.")
+        saveAndTest(contactTypeInstance)
+    }
+
+    def createBaseInventoryItemPurchaseTypes() {
+
+        // InventoryItemPurchaseType
+        def inventoryItemPurchaseTypeInstance
+
+        // InventoryItemPurchaseType #1
+        inventoryItemPurchaseTypeInstance = new InventoryItemPurchaseType(name: "Order Placed",
+                                                                                description: "Order has been placed.")
+        saveAndTest(inventoryItemPurchaseTypeInstance)
+
+        // InventoryItemPurchaseType #2
+        inventoryItemPurchaseTypeInstance = new InventoryItemPurchaseType(name: "Received B/order To Come",
+                                                                                description: "Order has been partially received.")
+        saveAndTest(inventoryItemPurchaseTypeInstance)
+
+        // InventoryItemPurchaseType #3
+        inventoryItemPurchaseTypeInstance = new InventoryItemPurchaseType(name: "Received Complete",
+                                                                                description: "Order has been partially received.")
+        saveAndTest(inventoryItemPurchaseTypeInstance)
+
+        // InventoryItemPurchaseType #4
+        inventoryItemPurchaseTypeInstance = new InventoryItemPurchaseType(name: "Invoice Approved",
+                                                                                description: "Invoice approved for payment.")
+        saveAndTest(inventoryItemPurchaseTypeInstance)
+    }
+
+    def createDemoSuppliers() {
+
+        // Supplier
+        def supplierInstance
+
+        // Supplier #1
+        supplierInstance = new Supplier(name: "OEM Distributors",
+                                                                        supplierType: SupplierType.get(2))
+        saveAndTest(supplierInstance)
+
+        // Supplier #2
+        supplierInstance = new Supplier(name: "Mex Holdings",
+                                                                        supplierType: SupplierType.get(3))
+        saveAndTest(supplierInstance)
+    }
+
+    def createDemoProductionReference() {
+
+        // ProductionReference
+        def productionReferenceInstance
+
+        // ProductionReference #1
+        productionReferenceInstance = new ProductionReference(name: "Monday Production")
+        saveAndTest(productionReferenceInstance)
+
+        // ProductionReference #2
+        productionReferenceInstance = new ProductionReference(name: "Tuesday Production")
+        saveAndTest(productionReferenceInstance)
+    }
+
+    void createDemoPurchasingGroups() {
+
+        // PurchasingGroup
+        def purchasingGroupInstance
+
+        purchasingGroupInstance = new PurchasingGroup(name:"R&M")
+        saveAndTest(purchasingGroupInstance)
+
+        purchasingGroupInstance = new PurchasingGroup(name:"Raw Materials")
+        saveAndTest(purchasingGroupInstance)
+
+        purchasingGroupInstance = new PurchasingGroup(name:"Safety")
+        saveAndTest(purchasingGroupInstance)
+    }
+
+    def createDemoCostCodes() {
+
+        // CostCode
+        def costCodeInstance
+
+        // CostCode #1
+        costCodeInstance = new CostCode(name: "Reelstand.172",
+                                                                    purchasingGroup: PurchasingGroup.get(1))
+        saveAndTest(costCodeInstance)
+
+        // CostCode #2
+        costCodeInstance = new CostCode(name: "Reelstand.CAPEX",
+                                                                    purchasingGroup: PurchasingGroup.get(1))
+        saveAndTest(costCodeInstance)
+
+        // CostCode #2
+        costCodeInstance = new CostCode(name: "PrintUnit.123",
+                                                                    purchasingGroup: PurchasingGroup.get(3))
+        saveAndTest(costCodeInstance)
+    }
+
+/*********************
+START OF TASK
+*********************/
+
+    def createBaseTaskGroups() {
+        //TaskGroup
+        def taskGroupInstance
+
+        //TaskGroup #1
+        taskGroupInstance = new TaskGroup(name:"Engineering Activites",
+                                                                            description:"Engineering daily activities")
+        saveAndTest(taskGroupInstance)
+
+        //TaskGroup #2
+        taskGroupInstance = new TaskGroup(name:"Production Activites",
+                                                                            description:"Production daily activities")
+        saveAndTest(taskGroupInstance)
+
+        //TaskGroup #3
+        taskGroupInstance = new TaskGroup(name:"New Projects",
+                                                                            description:"New site projects")
+        saveAndTest(taskGroupInstance)
+
+        //TaskGroup #4
+        taskGroupInstance = new TaskGroup(name:"Electrical Dayshift",
+                                                                            description:"Group for dayshift electrical tasks")
+        saveAndTest(taskGroupInstance)
+
+        //TaskGroup #5
+        taskGroupInstance = new TaskGroup(name:"Electrical Nightshift",
+                                                                            description:"Group for dayshift mechanical tasks")
+        saveAndTest(taskGroupInstance)
+
+        //TaskGroup #6
+        taskGroupInstance = new TaskGroup(name:"Mechanical Dayshift",
+                                                                            description:"Group for nightshift electrical tasks")
+        saveAndTest(taskGroupInstance)
+
+        //TaskGroup #7
+        taskGroupInstance = new TaskGroup(name:"Mechanical Nightshift",
+                                                                            description:"Group for nightshift mechanical tasks")
+        saveAndTest(taskGroupInstance)
+    }
+
+    def createBaseTaskStatus() {
+
+        //TaskStatus
+        def taskStatusInstance
+
+        taskStatusInstance = new TaskStatus(name:"Not Started") // #1
+        saveAndTest(taskStatusInstance)
+
+        taskStatusInstance = new TaskStatus(name:"In Progress") // #2
+        saveAndTest(taskStatusInstance)
+
+        taskStatusInstance = new TaskStatus(name:"Complete") // #3
+        saveAndTest(taskStatusInstance)
+    }
+
+    def createBaseTaskPriorities() {
+
+        //TaskPriority
+        def taskPriorityInstance
+
+        taskPriorityInstance = new TaskPriority(name:"0 - Immediate") // #1
+        saveAndTest(taskPriorityInstance)
+
+        taskPriorityInstance = new TaskPriority(name:"1 - Very High") // #2
+        saveAndTest(taskPriorityInstance)
+
+        taskPriorityInstance = new TaskPriority(name:"2 - High") // #3
+        saveAndTest(taskPriorityInstance)
+
+        taskPriorityInstance = new TaskPriority(name:"3 - Normal") // #4
+        saveAndTest(taskPriorityInstance)
+
+        taskPriorityInstance = new TaskPriority(name:"4 - Low") // #5
+        saveAndTest(taskPriorityInstance)
+
+        taskPriorityInstance = new TaskPriority(name:"5 - Minor") //  #6
+        saveAndTest(taskPriorityInstance)
+    }
+
+    def createBaseTaskBudgetStatus() {
+
+        //TaskBudgetStatus
+        def taskBudgetStatusInstance
+
+        taskBudgetStatusInstance = new TaskBudgetStatus(name:"Unplanned") // #1
+        saveAndTest(taskBudgetStatusInstance)
+
+        taskBudgetStatusInstance = new TaskBudgetStatus(name:"Planned") // #2
+        saveAndTest(taskBudgetStatusInstance)
+    }
+
+    def createBaseTaskTypes() {
+
+        //TaskType
+        def taskTypeInstance
+
+        taskTypeInstance = new TaskType(name:"Immediate Callout") // #1
+        saveAndTest(taskTypeInstance)
+
+        taskTypeInstance = new TaskType(name:"Unscheduled Breakin") // #2
+        saveAndTest(taskTypeInstance)
+
+        taskTypeInstance = new TaskType(name:"Scheduled") // #3
+        saveAndTest(taskTypeInstance)
+
+        taskTypeInstance = new TaskType(name:"Preventative Maintenance") // #4
+        saveAndTest(taskTypeInstance)
+
+        taskTypeInstance = new TaskType(name:"Project") // #5
+        saveAndTest(taskTypeInstance)
+
+        taskTypeInstance = new TaskType(name:"Parent PM") // #6
+        saveAndTest(taskTypeInstance)
+    }
+
+    def createBaseTaskModificationTypes() {
+
+        //ModificationType
+        def taskModificationTypeInstance
+        taskModificationTypeInstance = new TaskModificationType(name:"Created").save()  // #1
+        taskModificationTypeInstance = new TaskModificationType(name:"Started").save()  // #2
+        taskModificationTypeInstance = new TaskModificationType(name:"Modified").save()  // #3
+        taskModificationTypeInstance = new TaskModificationType(name:"Completed").save()  // #4
+        taskModificationTypeInstance = new TaskModificationType(name:"Reopened").save()  // #5
+        taskModificationTypeInstance = new TaskModificationType(name:"Trashed").save()  // #6
+        taskModificationTypeInstance = new TaskModificationType(name:"Restored").save()  // #7
+        taskModificationTypeInstance = new TaskModificationType(name:"Approved").save()  // #8
+        taskModificationTypeInstance = new TaskModificationType(name:"Renege approval").save()  // #9
+        taskModificationTypeInstance = new TaskModificationType(name:"Modified (Assigned Groups)").save()  // #10
+        taskModificationTypeInstance = new TaskModificationType(name:"Modified (Assigned Persons)").save()  // #11
+        taskModificationTypeInstance = new TaskModificationType(name:"Modified (Flagged for attention)").save()  // #12
+        taskModificationTypeInstance = new TaskModificationType(name:"Modified (Attention flag cleared)").save()  // #13
+    }
+
+    def createDemoTasks() {
+
+        def taskResult
+        def p = [:]
+
+        //Task #1
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
+                taskPriority:TaskPriority.get(2),
+                taskType:TaskType.get(1),
+                leadPerson:Person.get(2),
+                primaryAsset:Asset.get(4),
+                description:"Level sensor not working",
+                comment:"Has been noted as problematic, try recalibrating.",
+                targetStartDate: dateUtilService.today,
+                targetCompletionDate: dateUtilService.today]
+
+        taskResult = taskService.save(p)
+        taskService.approve(taskResult.taskInstance)
+
+        //Task #2
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
+                taskPriority:TaskPriority.get(2),
+                taskType:TaskType.get(3),
+                leadPerson:Person.get(5),
+                primaryAsset:Asset.get(4),
+                description:"Some follow-up work",
+                comment:"Some help required",
+                targetStartDate: dateUtilService.tomorrow,
+                targetCompletionDate: dateUtilService.tomorrow,
+                parentTask: Task.list()[0]]
+
+        taskResult = taskService.save(p)
+        taskService.approve(taskResult.taskInstance)
+
+        //Task #3
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
+                taskPriority:TaskPriority.get(2),
+                taskType:TaskType.get(3),
+                leadPerson:Person.get(5),
+                primaryAsset:Asset.get(4),
+                description:"A Sub Task can be created from the 'Sub Task' tab.",
+                comment:"Some help required",
+                targetStartDate: dateUtilService.yesterday,
+                targetCompletionDate: dateUtilService.yesterday,
+                parentTask: Task.list()[0]]
+
+        taskResult = taskService.save(p)
+        taskService.approve(taskResult.taskInstance)
+
+        //Task #4
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
+                taskPriority:TaskPriority.get(2),
+                taskType:TaskType.get(2),
+                leadPerson:Person.get(4),
+                primaryAsset:Asset.get(4),
+                description:"Please replace sensor at next available opportunity.",
+                comment:"Nothing else has worked. So we now require the part to be replaced.",
+                targetStartDate: dateUtilService.today,
+                targetCompletionDate: dateUtilService.oneWeekFromNow,
+                parentTask: Task.list()[0]]
+
+        taskResult = taskService.save(p)
+        taskService.approve(taskResult.taskInstance)
+
+        //Task #5
+        p = [taskGroup:TaskGroup.findByName("Production Activites"),
+                taskPriority:TaskPriority.get(2),
+                taskType:TaskType.get(3),
+                leadPerson:Person.get(6),
+                primaryAsset:Asset.get(1),
+                description:"Production Task",
+                comment:"Production task for specific production run or shift",
+                targetStartDate: dateUtilService.today - 6,
+                targetCompletionDate: dateUtilService.today - 6]
+
+        taskResult = taskService.save(p)
+        taskService.approve(taskResult.taskInstance)
+
+        //Task #6
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
+                taskPriority:TaskPriority.get(4),
+                taskType:TaskType.get(6),
+                leadPerson:Person.get(4),
+                primaryAsset:Asset.get(2),
+                description:"This is a recurring preventative maintenance task.",
+                comment:"If there is a parent task specified then this is a generated sub task, if there is a recurring schedule specified then this is a parent task.",
+                targetStartDate: dateUtilService.today,
+                targetCompletionDate: dateUtilService.today + 30]
+
+        taskResult = taskService.save(p)
+        taskService.approve(taskResult.taskInstance)
+
+        //Task #7
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
+                taskPriority:TaskPriority.get(4),
+                taskType:TaskType.get(6),
+                leadPerson:Person.get(4),
+                primaryAsset:Asset.get(2),
+                description:"100hr Service.",
+                comment:"Based on OEM service.",
+                targetStartDate: dateUtilService.today,
+                targetCompletionDate: dateUtilService.today + 1]
+
+        taskResult = taskService.save(p)
+        taskService.approve(taskResult.taskInstance)
+    }
+
+    def createBaseEntryTypes() {
+
+        //EntryType
+        def entryTypeInstance
+
+        entryTypeInstance = new EntryType(name:"Fault") // #1
+        saveAndTest(entryTypeInstance)
+
+        entryTypeInstance = new EntryType(name:"Cause") // #2
+        saveAndTest(entryTypeInstance)
+
+        entryTypeInstance = new EntryType(name:"Work Done") // #3
+        saveAndTest(entryTypeInstance)
+
+        entryTypeInstance = new EntryType(name:"Production Note") // #4
+        saveAndTest(entryTypeInstance)
+
+        entryTypeInstance = new EntryType(name:"Work Request") // #5
+        saveAndTest(entryTypeInstance)
+    }
+
+    def createDemoEntries() {
+
+        def entryResult
+        def p = [:]
+
+        //Entry #1
+        p = [task: Task.list()[0],
+                entryType: EntryType.get(1),
+                comment: "This level sensor is causing us trouble.",
+                durationMinute: 20]
+
+        entryResult = taskService.saveEntry(p)
+
+        //Entry #2
+        p = [task: Task.list()[0],
+                entryType: EntryType.get(3),
+                comment: "Cleaned sensor, see how it goes.",
+                durationMinute: 30]
+
+        entryResult = taskService.saveEntry(p)
+
+        //Entry #3
+        p = [task: Task.list()[0],
+                entryType: EntryType.get(3),
+                comment: "Checked up on it later and sensor is dropping out intermittently, created sub task to replace sensor.",
+                durationMinute: 20]
+
+        entryResult = taskService.saveEntry(p)
+
+        //Entry #4
+        p = [task: Task.list()[4],
+                entryType: EntryType.get(3),
+                comment: "Work done as per procedure.",
+                durationMinute: 55]
+
+        entryResult = taskService.saveEntry(p)
+    }
+
+    def createDemoAssignedGroups() {
+
+        def result
+        def p = [:]
+
+        //AssignedGroup #1
+        p = [personGroup: PersonGroup.get(1),
+                task: Task.list()[0],
+                estimatedHour: 2,
+                estimatedMinute: 30]
+        result = assignedGroupService.save(p)
+
+        //AssignedGroup #2
+        p = [personGroup: PersonGroup.get(2),
+                task: Task.list()[0],
+                estimatedHour: 1,
+                estimatedMinute: 0]
+        result = assignedGroupService.save(p)
+    }
+
+    def createDemoAssignedPersons() {
+
+        def result
+        def p = [:]
+
+        //AssignedPerson #1
+        p = [person: Person.get(3), // Demo Manager.
+                task: Task.list()[5],
+                estimatedHour: 1,
+                estimatedMinute: 20]
+        result = assignedPersonService.save(p)
+
+        //AssignedPerson #2
+        p = [person: Person.get(4), // Demo User.
+                task: Task.list()[5],
+                estimatedHour: 1,
+                estimatedMinute: 20]
+        result = assignedPersonService.save(p)
+
+        //AssignedPerson #3
+        p = [person: Person.get(3), // Demo Manager.
+                task: Task.list()[6],
+                estimatedHour: 3,
+                estimatedMinute: 30]
+        result = assignedPersonService.save(p)
+
+        //AssignedPerson #4
+        p = [person: Person.get(4), // Demo User.
+                task: Task.list()[6],
+                estimatedHour: 3,
+                estimatedMinute: 30]
+        result = assignedPersonService.save(p)
+    }
+
+    def createBaseMaintenancePolicies() {
+
+        //MaintenancePolicy
+        def maintenancePolicyInstance
+
+        //MaintenancePolicy #1
+        maintenancePolicyInstance = new MaintenancePolicy(name: "Fixed Time")
+        saveAndTest(maintenancePolicyInstance)
+
+        //MaintenancePolicy #2
+        maintenancePolicyInstance = new MaintenancePolicy(name: "Condition Based Online")
+        saveAndTest(maintenancePolicyInstance)
+
+        //MaintenancePolicy #3
+        maintenancePolicyInstance = new MaintenancePolicy(name: "Condition Based Offline")
+        saveAndTest(maintenancePolicyInstance)
+
+        //MaintenancePolicy #4
+        maintenancePolicyInstance = new MaintenancePolicy(name: "Design Out")
+        saveAndTest(maintenancePolicyInstance)
+
+        //MaintenancePolicy #5
+        maintenancePolicyInstance = new MaintenancePolicy(name: "Operate To Failure")
+        saveAndTest(maintenancePolicyInstance)
+
+        //MaintenancePolicy #6
+        maintenancePolicyInstance = new MaintenancePolicy(name: "Regulatory Requirement")
+        saveAndTest(maintenancePolicyInstance)
+
+        //MaintenancePolicy #7
+        maintenancePolicyInstance = new MaintenancePolicy(name: "Hidden Function Test")
+        saveAndTest(maintenancePolicyInstance)
+    }
+
+    def createDemoTaskProcedure() {
+
+        //TaskProcedure
+        def taskProcedureInstance
+
+        taskProcedureInstance = new TaskProcedure(name: "Daily check")
+        saveAndTest(taskProcedureInstance)
+        taskProcedureInstance.addToTasks(Task.list()[0])
+
+        taskProcedureInstance = new TaskProcedure(name: "100hr Service")
+        saveAndTest(taskProcedureInstance)
+        taskProcedureInstance.addToTasks(Task.list()[6])
+    }
+
+    def createDemoMaintenanceActions() {
+
+        //MaintenanceAction
+        def maintenanceActionInstance
+
+        //MaintenanceAction #1
+        maintenanceActionInstance = new MaintenanceAction(description: "Check all E-stops, activate E-stops S1-S12 and ensure machine cannot run",
+                                                                                                        procedureStepNumber: 10,
+                                                                                                        maintenancePolicy: MaintenancePolicy.get(1),
+                                                                                                        taskProcedure: TaskProcedure.get(1))
+        saveAndTest(maintenanceActionInstance)
+
+        //MaintenanceAction #2
+        maintenanceActionInstance = new MaintenanceAction(description: "Do more pushups",
+                                                                                                        procedureStepNumber: 20,
+                                                                                                        maintenancePolicy: MaintenancePolicy.get(1),
+                                                                                                        taskProcedure: TaskProcedure.get(1))
+        saveAndTest(maintenanceActionInstance)
+
+        //MaintenanceAction #3
+        maintenanceActionInstance = new MaintenanceAction(description: "Ok just one more pushup",
+                                                                                                        procedureStepNumber: 30,
+                                                                                                        maintenancePolicy: MaintenancePolicy.get(1),
+                                                                                                        taskProcedure: TaskProcedure.get(1))
+        saveAndTest(maintenanceActionInstance)
+    }
+
+    def createDemoTaskRecurringSchedules() {
+
+        //TaskRecurringSchedule
+        def taskRecurringScheduleInstance
+
+        //TaskRecurringSchedule #1
+        taskRecurringScheduleInstance = new TaskRecurringSchedule(task: Task.list()[0],
+                                                                                                    recurEvery: 1,
+                                                                                                    recurPeriod: Period.get(2),
+                                                                                                    nextTargetStartDate: dateUtilService.today,
+                                                                                                    generateAhead: 1,
+                                                                                                    taskDuration: 2,
+                                                                                                    taskDurationPeriod: Period.get(1),
+                                                                                                    enabled: false)
+        saveAndTest(taskRecurringScheduleInstance)
+
+        //TaskRecurringSchedule #2
+        taskRecurringScheduleInstance = new TaskRecurringSchedule(task: Task.list()[5],
+                                                                                                    recurEvery: 1,
+                                                                                                    recurPeriod: Period.get(1),
+                                                                                                    nextTargetStartDate: dateUtilService.today,
+                                                                                                    generateAhead: 1,
+                                                                                                    taskDuration: 1,
+                                                                                                    taskDurationPeriod: Period.get(1),
+                                                                                                    enabled: true)
+        saveAndTest(taskRecurringScheduleInstance)
+
+        //TaskRecurringSchedule #3
+        taskRecurringScheduleInstance = new TaskRecurringSchedule(task: Task.list()[6],
+                                                                                                    recurEvery: 1,
+                                                                                                    recurPeriod: Period.get(1),
+                                                                                                    nextTargetStartDate: dateUtilService.today,
+                                                                                                    generateAhead: 1,
+                                                                                                    taskDuration: 1,
+                                                                                                    taskDurationPeriod: Period.get(1),
+                                                                                                    enabled: true)
+        saveAndTest(taskRecurringScheduleInstance)
+    }
+
+/*************************
+START OF INVENTORY
+**************************/
+
+    def createDemoInventoryStores() {
+
+        //InventoryStore
+        def inventoryStoreInstance
+
+        inventoryStoreInstance = new InventoryStore(site: Site.get(1), name: "Store #1")
+        saveAndTest(inventoryStoreInstance)
+
+        inventoryStoreInstance = new InventoryStore(site: Site.get(2), name: "Store #2")
+        saveAndTest(inventoryStoreInstance)
+    }
+
+    def createDemoInventoryLocations() {
+
+        // InventoryLocation
+        def inventoryLocation
+
+        inventoryLocation = new InventoryLocation(inventoryStore: InventoryStore.get(1), name: "A1-2")
+        saveAndTest(inventoryLocation)
+
+        inventoryLocation = new InventoryLocation(inventoryStore: InventoryStore.get(2), name: "C55")
+        saveAndTest(inventoryLocation)
+    }
+
+    def createDemoInventoryGroups() {
+
+        //InventoryGroup
+        def inventoryGroupInstance
+
+        //InventoryGroup #1
+        inventoryGroupInstance = new InventoryGroup(name: "Misc")
+        saveAndTest(inventoryGroupInstance)
+
+        //InventoryGroup #2
+        inventoryGroupInstance = new InventoryGroup(name: "Electrical")
+        saveAndTest(inventoryGroupInstance)
+
+        //InventoryGroup #3
+        inventoryGroupInstance = new InventoryGroup(name: "Mechanical")
+        saveAndTest(inventoryGroupInstance)
+
+        //InventoryGroup #4
+        inventoryGroupInstance = new InventoryGroup(name: "Production")
+        saveAndTest(inventoryGroupInstance)
+    }
+
+    def createBaseInventoryTypes() {
+
+        //InventoryType
+        def inventoryTypeInstance
+
+        //InventoryType #1
+        inventoryTypeInstance = new InventoryType(name: "Consumable",
+                                                                                description: "Standard inventory items that are received as new.")
+        saveAndTest(inventoryTypeInstance)
+
+        //InventoryType #2
+        inventoryTypeInstance = new InventoryType(name: "Rotable",
+                                                                                description: "Repairable inventory items that are to be tracked as rotables.")
+        saveAndTest(inventoryTypeInstance)
+
+        //InventoryType #3
+        inventoryTypeInstance = new InventoryType(name: "Service",
+                                                                                description: "Provided services from contractors etc.")
+        saveAndTest(inventoryTypeInstance)
+
+        //InventoryType #4
+        inventoryTypeInstance = new InventoryType(name: "Tool",
+                                                                                description: "Tools that are held as inventory.")
+        saveAndTest(inventoryTypeInstance)
+    }
+
+    def createBaseInventoryMovementTypes() {
+
+        // InventoryMovementType
+        def inventoryMovementTypeInstance
+
+        // InventoryMovementType #1
+        inventoryMovementTypeInstance = new InventoryMovementType(name: "Used",
+                                                                                                                        incrementsInventory: false)
+        saveAndTest(inventoryMovementTypeInstance)
+
+        // InventoryMovementType #2
+        inventoryMovementTypeInstance = new InventoryMovementType(name: "Repaired",
+                                                                                                                        incrementsInventory: true)
+        saveAndTest(inventoryMovementTypeInstance)
+
+        // InventoryMovementType #3
+        inventoryMovementTypeInstance = new InventoryMovementType(name: "Purchase Received",
+                                                                                                                        incrementsInventory: true)
+        saveAndTest(inventoryMovementTypeInstance)
+
+        // InventoryMovementType #4
+        inventoryMovementTypeInstance = new InventoryMovementType(name: "Correction Increase",
+                                                                                                                        incrementsInventory: true)
+        saveAndTest(inventoryMovementTypeInstance)
+
+        // InventoryMovementType #5
+        inventoryMovementTypeInstance = new InventoryMovementType(name: "Correction Decrease",
+                                                                                                                        incrementsInventory: false)
+        saveAndTest(inventoryMovementTypeInstance)
+    }
+
+    def createDemoInventoryItems() {
+
+        //InventoryItem
+        def inventoryItemInstance
+        def currency = Currency.getInstance('AUD')
+
+        def pictureResource = grailsApplication.mainContext.getResource('images/logo.png')
+
+        //InventoryItem #1
+        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(1),
+                                                                                    inventoryType: InventoryType.get(1),
+                                                                                    unitOfMeasure: UnitOfMeasure.get(2),
+                                                                                    inventoryLocation: InventoryLocation.get(1),
+                                                                                    name: "Hemp rope",
+                                                                                    description: "Natural hemp rope.",
+                                                                                    estimatedUnitPriceAmount: 1.23,
+                                                                                    estimatedUnitPriceCurrency: currency,
+                                                                                    unitsInStock: 2,
+                                                                                    reorderPoint: 0)
+        saveAndTest(inventoryItemInstance)
+        inventoryItemService.savePicture(inventoryItemInstance, pictureResource)
+
+        //InventoryItem #2
+        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(1),
+                                                                                    inventoryType: InventoryType.get(1),
+                                                                                    unitOfMeasure: UnitOfMeasure.get(2),
+                                                                                    inventoryLocation: InventoryLocation.get(1),
+                                                                                    name: "Cotton Rope 12mm",
+                                                                                    description: "A soft natural rope made from cotton.",
+                                                                                    estimatedUnitPriceAmount: 2.50,
+                                                                                    estimatedUnitPriceCurrency: currency,
+                                                                                    unitsInStock: 2,
+                                                                                    reorderPoint: 0)
+        saveAndTest(inventoryItemInstance)
+        inventoryItemService.savePicture(inventoryItemInstance, pictureResource)
+
+        //InventoryItem #3
+        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(3),
+                                                                                    inventoryType: InventoryType.get(1),
+                                                                                    unitOfMeasure: UnitOfMeasure.get(1),
+                                                                                    inventoryLocation: InventoryLocation.get(2),
+                                                                                    name: "2305-2RS",
+                                                                                    description: "Bearing 25x62x24mm double row self aligning ball",
+                                                                                    estimatedUnitPriceAmount: 5,
+                                                                                    estimatedUnitPriceCurrency: currency,
+                                                                                    unitsInStock: 3,
+                                                                                    reorderPoint: 2)
+        saveAndTest(inventoryItemInstance)
+        inventoryItemService.savePicture(inventoryItemInstance, pictureResource)
+
+        //InventoryItem #4
+        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(2),
+                                                                                    inventoryType: InventoryType.get(1),
+                                                                                    unitOfMeasure: UnitOfMeasure.get(1),
+                                                                                    inventoryLocation: InventoryLocation.get(2),
+                                                                                    name: "L1592-K10",
+                                                                                    description: "10kW contactor",
+                                                                                    estimatedUnitPriceAmount: 180,
+                                                                                    estimatedUnitPriceCurrency: currency,
+                                                                                    unitsInStock: 4,
+                                                                                    reorderPoint: 0)
+        saveAndTest(inventoryItemInstance)
+        inventoryItemService.savePicture(inventoryItemInstance, pictureResource)
+
+        //InventoryItem #5
+        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(3),
+                                                                                    inventoryType: InventoryType.get(1),
+                                                                                    unitOfMeasure: UnitOfMeasure.get(1),
+                                                                                    inventoryLocation: InventoryLocation.get(2),
+                                                                                    name: "6205-ZZ",
+                                                                                    description: "Bearing 25x52x15mm single row ball shielded",
+                                                                                    estimatedUnitPriceAmount: 3.45,
+                                                                                    estimatedUnitPriceCurrency: currency,
+                                                                                    unitsInStock: 5,
+                                                                                    reorderPoint: 2)
+        saveAndTest(inventoryItemInstance)
+        inventoryItemService.savePicture(inventoryItemInstance, pictureResource)
+    }
+
+/*******************
+START OF ASSET
+*******************/
+
+    def createBaseExtenededAttributeTypes() {
+
+        //ExtendedAttributeType
+        def extendedAttributeTypeInstance
+
+        //ExtendedAttributeType #1
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Model Number")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #2
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Purchase Cost")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #3
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Serial Number")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #4
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Manufactured Date")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #5
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Location Description")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #6
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Cost Centre")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #7
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Cost Code")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #8
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Manufacturer")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #9
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "ecr")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #10
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Risk Level")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #11
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Safe Work Procedure")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #12
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Regulatory Requirement")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #13
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Maintenance % Completion")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #14
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Registration Required")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #15
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Registration Expiry Date")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #16
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Asset Condition")
+        saveAndTest(extendedAttributeTypeInstance)
+
+        //ExtendedAttributeType #17
+        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Asset Number")
+        saveAndTest(extendedAttributeTypeInstance)
+    }
+
+    def createDemoSections() {
+
+        //Section
+        def sectionInstance
+
+        //Section #1
+        sectionInstance = new Section(name: "A-Press",
+                                                                description: "Press Section",
+                                                                site: Site.get(3),
+                                                                department: Department.get(1))
+        saveAndTest(sectionInstance)
+
+        //Section #2
+        sectionInstance = new Section(name: "CSM-Delig",
+                                                                description: "Pulp Delignification",
+                                                                site: Site.get(1),
+                                                                department: Department.get(2))
+        saveAndTest(sectionInstance)
+
+        //Section #3
+        sectionInstance = new Section(name: "CSM-Aux",
+                                                                description: "Auxilliary Section",
+                                                                site: Site.get(1),
+                                                                department: Department.get(1))
+        saveAndTest(sectionInstance)
+    }
+
+    def createDemoAssetTree() {
+
+        //Asset
+        def assetInstance
+
+        //Asset #1
+        def assetInstance1 = new Asset(name: "Print Tower 22",
+                                                                description: "Complete Printing Asset #22",
+                                                                comment: "Includes everthing directly attached to the tower.",
+                                                                section: Section.get(1))
+        saveAndTest(assetInstance1)
+//        assetInstance.addToMaintenanceActions(MaintenanceAction.get(1))
+
+        //Asset #2
+        def assetInstance2 = new Asset(name: "Print Tower 21",
+                                                                description: "Complete Printing Asset #21",
+                                                                section: Section.get(1))
+        saveAndTest(assetInstance2)
+
+        //Asset #3
+        def assetInstance3 = new Asset(name: "Print Tower 23",
+                                                                description: "Complete Printing Asset #23",
+                                                                section: Section.get(1))
+        saveAndTest(assetInstance3)
+
+        //Asset #4
+        def assetInstance4 = new Asset(name: "C579",
+                                                                description: "RO #1",
+                                                                section: Section.get(2))
+        saveAndTest(assetInstance4)
+
+        //AssetSubItem
+        def assetSubItemInstance
+
+        //AssetSubItem #1 Level1
+        def assetSubItemInstance1 = new AssetSubItem(name: "Print Tower",
+                                                                                            description: "Common sub asset.")
+        saveAndTest(assetSubItemInstance1)
+
+        // Add assetSubItemInstance1 to some assets.
+        assetInstance1.addToAssetSubItems(assetSubItemInstance1)
+        assetInstance2.addToAssetSubItems(assetSubItemInstance1)
+        assetInstance3.addToAssetSubItems(assetSubItemInstance1)
+
+        //AssetSubItem #2 Level1
+        def assetSubItemInstance2 = new AssetSubItem(name: "C579-44",
+                                                                                            description: "Tanks and towers")
+        saveAndTest(assetSubItemInstance2)
+
+        // Add assetSubItemInstance2 to some assets.
+        assetInstance4.addToAssetSubItems(assetSubItemInstance2)
+
+        //AssetSubItem #3 Level1
+        def assetSubItemInstance3 = new AssetSubItem(name: "C579-20",
+                                                                                            description: "Control Loops")
+        saveAndTest(assetSubItemInstance3)
+
+        // Add assetSubItemInstance3 to some assets.
+        assetInstance4.addToAssetSubItems(assetSubItemInstance3)
+
+        //AssetSubItem #4 Level2
+        assetSubItemInstance = new AssetSubItem(name: "C579-TK-0022",
+                                                                                            description: "Blow Tank",
+                                                                                            parentItem: AssetSubItem.get(2))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #5 Level2
+        assetSubItemInstance = new AssetSubItem(name: "C579-TK-0023",
+                                                                                            description: "Reactor Tower",
+                                                                                            parentItem: AssetSubItem.get(2))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #6 Level2
+        assetSubItemInstance = new AssetSubItem(name: "Print Unit",
+                                                                                    description: "Print Unit - Common Level 2 sub item.",
+                                                                                    parentItem: AssetSubItem.get(1))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #7 Level2
+        assetSubItemInstance = new AssetSubItem(name: "1925365",
+                                                                                    description: "Agitator",
+                                                                                    parentItem: AssetSubItem.get(4))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #8 Level2
+        assetSubItemInstance = new AssetSubItem(name: "1925366",
+                                                                                    description: "Scraper",
+                                                                                    parentItem: AssetSubItem.get(4))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #9 Level3
+        assetSubItemInstance = new AssetSubItem(name: "Motor",
+                                                                                    description: "Motor - Level 3 sub item",
+                                                                                    parentItem: AssetSubItem.get(6))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #10 Level3
+        assetSubItemInstance = new AssetSubItem(name: "Gearbox",
+                                                                                    description: "Gearbox - Level 3 sub item, gearbox",
+                                                                                    parentItem: AssetSubItem.get(6))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #11 Level4
+        assetSubItemInstance = new AssetSubItem(name: "DS Bearing",
+                                                                                    description: "Drive Side Bearing",
+                                                                                    parentItem: AssetSubItem.get(9))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #12 Level4
+        assetSubItemInstance = new AssetSubItem(name: "NDS Bearing",
+                                                                                    description: "Non Drive Side Bearing",
+                                                                                    parentItem: AssetSubItem.get(9))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #13 Level2
+        assetSubItemInstance = new AssetSubItem(name: "C579-F-0001",
+                                                                                    description: "Weak Caustic Flow",
+                                                                                    parentItem: AssetSubItem.get(3))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #14 Level3
+        assetSubItemInstance = new AssetSubItem(name: "C579-FT-0002",
+                                                                                    description: "Weak Caustic Flow Transmitter",
+                                                                                    parentItem: AssetSubItem.get(13))
+        saveAndTest(assetSubItemInstance)
+
+        //AssetSubItem #15 Level3
+        assetSubItemInstance = new AssetSubItem(name: "C579-PT-0003",
+                                                                                    description: "Weak Caustic Pressure Transmitter",
+                                                                                    parentItem: AssetSubItem.get(13))
+        saveAndTest(assetSubItemInstance)
+    } // createDemoAssetTree()
+
+    def createDemoAssetSubItemExtendedAttributes() {
+
+        //AssetSubItemExtendedAttribute
+        def assetSubItemExtendedAttributeInstance
+
+        //AssetSubItemExtendedAttribute #1
+        assetSubItemExtendedAttributeInstance = new AssetSubItemExtendedAttribute(value: "United Press",
+                                                                                                                    assetSubItem: AssetSubItem.get(1),
+                                                                                                                    extendedAttributeType: ExtendedAttributeType.get(8)) // Manufacturer.
+        saveAndTest(assetSubItemExtendedAttributeInstance)
+
+        //AssetSubItemExtendedAttribute #2
+        assetSubItemExtendedAttributeInstance = new AssetSubItemExtendedAttribute(value: "PU Mark 2",
+                                                                                                                    assetSubItem: AssetSubItem.get(1),
+                                                                                                                    extendedAttributeType: ExtendedAttributeType.get(1)) // Model Number.
+        saveAndTest(assetSubItemExtendedAttributeInstance)
+
+        //AssetSubItemExtendedAttribute #3
+        assetSubItemExtendedAttributeInstance = new AssetSubItemExtendedAttribute(value: "765895",
+                                                                                                                    assetSubItem: AssetSubItem.get(1),
+                                                                                                                    extendedAttributeType: ExtendedAttributeType.get(3)) // Serial Number.
+        saveAndTest(assetSubItemExtendedAttributeInstance)
+
+        //AssetSubItemExtendedAttribute #4
+        assetSubItemExtendedAttributeInstance = new AssetSubItemExtendedAttribute(value: "Jan-2003",
+                                                                                                                    assetSubItem: AssetSubItem.get(1),
+                                                                                                                    extendedAttributeType: ExtendedAttributeType.get(4)) // Manufactured Date.
+        saveAndTest(assetSubItemExtendedAttributeInstance)
+
+    }
+
+    def createDemoAssetExtendedAttributes() {
+
+        //AssetExtendedAttribute
+        def assetExtendedAttributeInstance
+
+        //AssetExtendedAttribute #1
+        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "On the far side of Tank 5",
+                                                                                                            asset: Asset.get(1),
+                                                                                                            extendedAttributeType: ExtendedAttributeType.get(5)) // Location Description.
+        saveAndTest(assetExtendedAttributeInstance)
+
+        //AssetExtendedAttribute #2
+        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "3",
+                                                                                                            asset: Asset.get(1),
+                                                                                                            extendedAttributeType: ExtendedAttributeType.get(9)) // ecr.
+        saveAndTest(assetExtendedAttributeInstance)
+
+        //AssetExtendedAttribute #3
+        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "RP-001",
+                                                                                                            asset: Asset.get(1),
+                                                                                                            extendedAttributeType: ExtendedAttributeType.get(17)) // Asset Number.
+        saveAndTest(assetExtendedAttributeInstance)
+
+        //AssetExtendedAttribute #4
+        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Good",
+                                                                                                            asset: Asset.get(1),
+                                                                                                            extendedAttributeType: ExtendedAttributeType.get(16)) // Asset Condition.
+        saveAndTest(assetExtendedAttributeInstance)
+
+        //AssetExtendedAttribute #5
+        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "TBA",
+                                                                                                            asset: Asset.get(1),
+                                                                                                            extendedAttributeType: ExtendedAttributeType.get(13)) // Maintenance % Completion.
+        saveAndTest(assetExtendedAttributeInstance)
+
+        //AssetExtendedAttribute #6
+        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Y",
+                                                                                                            asset: Asset.get(1),
+                                                                                                            extendedAttributeType: ExtendedAttributeType.get(14)) // Registration Required.
+        saveAndTest(assetExtendedAttributeInstance)
+
+        //AssetExtendedAttribute #7
+        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Feb-2009",
+                                                                                                            asset: Asset.get(1),
+                                                                                                            extendedAttributeType: ExtendedAttributeType.get(15)) // Registration Expiry Date.
+        saveAndTest(assetExtendedAttributeInstance)
+
+        //AssetExtendedAttribute #8
+        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "N",
+                                                                                                            asset: Asset.get(1),
+                                                                                                            extendedAttributeType: ExtendedAttributeType.get(12)) // Regulatory Requirement.
+        saveAndTest(assetExtendedAttributeInstance)
+
+        //AssetExtendedAttribute #9
+        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "Med",
+                                                                                                            asset: Asset.get(1),
+                                                                                                            extendedAttributeType: ExtendedAttributeType.get(10)) // Risk Level.
+        saveAndTest(assetExtendedAttributeInstance)
+
+        //AssetExtendedAttribute #10
+        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "WP-003",
+                                                                                                            asset: Asset.get(1),
+                                                                                                            extendedAttributeType: ExtendedAttributeType.get(11)) // Safe Work Procedure.
+        saveAndTest(assetExtendedAttributeInstance)
+    }
+
+    /**
+    * SearchableIndex and mirroring is disabled at startup.
+    * Use this to start indexing after creating bootstrap data.
+    * @param indexInNewThread Whether to run the index in a new thread, defaults to true.
+    */
+    def startSearchableIndex(Boolean indexInNewThread = true) {
+        log.info "Start mirroring searchable index."
+        ConfigurationHolder.config.appSearchable.cascadeOnUpdate = true
+        searchableService.startMirroring()
+        if(indexInNewThread) {
+            Thread.start {
+                log.info "Rebuilding searchable index, bulkIndex (new thread)."
+                searchableService.index()
+                log.info "Rebuilding searchable index, complete."
+            }
+        }
+        else {
+            log.info "Rebuilding searchable index, bulkIndex."
+            searchableService.index()
+            log.info "Rebuilding searchable index, complete."
+        }
+    }
+
+    /**
+    * Searchable index and mirroring during bulk data creation may be slow.
+    * Use this to stop indexing and restart with startSearchableIndex() after data creation.
+    */
+    def stopSearchableIndex() {
+        log.info "Stop mirroring searchable index."
+        ConfigurationHolder.config.appSearchable.cascadeOnUpdate = false
+        searchableService.stopMirroring()
+    }
+
+    /**
+    * Call this function instead of .save()
+    */
+    private boolean saveAndTest(object) {
+        if(!object.save()) {
+//             DemoDataSuccessful = false
+            log.error "'${object}' failed to save!"
+            log.error object.errors
+            return false
+        }
+        return true
+    }
+
+} // end of class
Index: branches/features/taskProcedureRework/grails-app/services/DateUtilService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/DateUtilService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/DateUtilService.groovy	(revision 753)
@@ -0,0 +1,165 @@
+import org.codehaus.groovy.runtime.TimeCategory
+// the above will be deprecated and replaced by: groovy.time.TimeCategory
+/// @todo: consider moving this to org.gnumims.DateUtil
+/// pros: easy to use in domain classes.
+/// cons: have to import so pulls in all referenced imports? Injection probably does that anyway.
+
+/**
+* Provides some convenience methods for working with dates.
+*/
+class DateUtilService {
+
+    boolean transactional = false
+    //static scope = "request"
+
+    /**
+    * Get the start of today.
+     * Can be call as dateUtilService.today or dateUtilService.getToday().
+     * @returns A Date object with today's date and all time fields set to 0.
+    */
+    public static Date getToday() {
+        return getMidnight(new Date())
+    }
+
+    /**
+    * Get the start of tomorrow.
+     * Can be call as dateUtilService.tomorrow or dateUtilService.getTomorrow().
+     * @returns A Date object with tomorrow's date and all time fields set to 0.
+    */
+    public static Date getTomorrow() {
+        return (getToday() + 1) as Date
+    }
+
+    /**
+    * Get the start of yesterday.
+     * Can be call as dateUtilService.yesterday or dateUtilService.getYesterday().
+     * @returns A Date object with yesterday's date and all time fields set to 0.
+    */
+    public static Date getYesterday() {
+        return (getToday() - 1) as Date
+    }
+
+    /**
+    * Get the start of the day one week ago.
+     * Can be call as dateUtilService.oneWeekAgo or dateUtilService.getOneWeekAgo().
+     * @returns A Date object with the date one week ago and all time fields set to 0.
+    */
+    public static Date getOneWeekAgo() {
+        return (getToday() - 7) as Date
+    }
+
+    /**
+    * Get the start of the day one week ago.
+     * Can be call as dateUtilService.oneWeekAgo or dateUtilService.getOneWeekAgo().
+     * @returns A Date object with the date one week ago and all time fields set to 0.
+    */
+    public static Date getOneWeekFromNow() {
+        return (getToday() + 7) as Date
+    }
+
+    /**
+    * Get the start of a given date by setting all time fields to 0.
+    * The Calendar.getInstance() or Calendar.instance factory returns a new calendar instance, usually
+    * a Gregorian calendar but using Calendar we don't have to worry about those details.
+    * The time fields are then set to zero and cal.getTime() or cal.time returns a java.util.Date object.
+    * @param date The Date object to start with.
+    * @returns A Date object having the given date and all time fields set to 0, so the very start of the given day.
+    */
+    public static Date getMidnight(Date date) {
+        Calendar cal = Calendar.instance
+        cal.setTime(date)
+        cal.set(Calendar.HOUR_OF_DAY, 0)
+        cal.set(Calendar.MINUTE, 0)
+        cal.set(Calendar.SECOND, 0)
+        cal.set(Calendar.MILLISECOND, 0)
+        cal.time
+    }
+
+    /**
+    * Get the date plus x weeks.
+    * @param date The Date object to start with, defaults to today.
+    * @param plusYears The number of weeks to add, defaults to 1.
+    * @returns A Date object adjusted by x weeks.
+    */
+    public static Date plusWeek(Date date = new Date(), Integer plusWeeks = 1) {
+        use(TimeCategory) {
+            date + plusWeeks.weeks
+        }
+    }
+
+    /**
+    * Get the date plus x months.
+    * @param date The Date object to start with, defaults to today.
+    * @param plusYears The number of months to add, defaults to 1.
+    * @returns A Date object adjusted by x months.
+    */
+    public static Date plusMonth(Date date = new Date(), Integer plusMonths = 1) {
+        use(TimeCategory) {
+            date + plusMonths.months
+        }
+    }
+
+    /**
+    * Get the date plus x years.
+    * @param date The Date object to start with, defaults to today.
+    * @param plusYears The number of years to add, defaults to 1.
+    * @returns A Date object adjusted by x years.
+    */
+    public static Date plusYear(Date date = new Date(), Integer plusYears = 1) {
+        use(TimeCategory) {
+            date + plusYears.years
+        }
+    }
+
+    /**
+    * Make a date object from supplied year, month, day values.
+    * The Calendar.getInstance() or Calendar.instance factory returns a new calendar instance, usually
+    * a Gregorian calendar but using Calendar we don't have to worry about those details.
+    * The time fields are set to zero and cal.getTime() or cal.time returns a java.util.Date object.
+    * @param year The year as a string or integer.
+    * @param month The month as a string or integer, defaults to 1 (i.e. January).
+    * @param day The day as a string or integer, defaults to 1.
+    * @returns A Date object having the given date and all time fields set to 0, so the very start of the given day.
+    */
+    public static Date makeDate(year, month=1, day=1) {
+        Calendar cal = Calendar.instance
+        cal.clear()
+        // Stupid month is 0-based, grumble.
+        cal.set(year.toInteger(), month.toInteger()-1, day.toInteger())
+        cal.time
+    }
+
+    /**
+    * Get the day of month from supplied date.
+    * @param date The date to extract the day of month from.
+    * @returns An integer representing the day of the month.
+    */
+    public static Integer getDayOfMonthFromDate(Date date) {
+        Calendar cal = Calendar.instance
+        cal.setTime(date)
+        cal.get(Calendar.DAY_OF_MONTH)
+    }
+
+    /**
+    * Get the month from supplied date.
+    * @param date The date to extract the month from.
+    * @returns An integer representing the month.
+    */
+    public static Integer getMonthFromDate(Date date) {
+        Calendar cal = Calendar.instance
+        cal.setTime(date)
+        cal.get(Calendar.MONTH) + 1 // Stupid month is 0-based, grumble.
+    }
+
+    /**
+    * Get the year from supplied date.
+    * @param date The date to extract the year from.
+    * @returns An integer representing the year.
+    */
+    public static Integer getYearFromDate(Date date) {
+        Calendar cal = Calendar.instance
+        cal.setTime(date)
+        cal.get(Calendar.YEAR)
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/InventoryCsvService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/InventoryCsvService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/InventoryCsvService.groovy	(revision 753)
@@ -0,0 +1,718 @@
+import grails.util.GrailsUtil
+import au.com.bytecode.opencsv.CSVWriter
+import au.com.bytecode.opencsv.CSVReader
+import org.apache.commons.lang.WordUtils
+
+/**
+ * Provides some csv import/export methods.
+ * Requires the opencsv jar to be available which is included in the grails-export plugin.
+ */
+class InventoryCsvService {
+
+    boolean transactional = false
+
+    def dateUtilService
+    def createDataService
+
+    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
+
+    def sessionFactory
+    def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP
+
+    /**
+    * Import inventory creating items as required.
+    * @param request The http request to run getFile against.
+    * Get file should return a csv format file containing the inventory as per template.
+    */
+    def importInventory(request) {
+        InventoryItem.withTransaction { status ->
+            def result = [:]
+
+            def kByteMultiplier = 1000
+            def fileMaxSize = 800 * kByteMultiplier
+            def logFileLink = g.link(controller: "appCore", action: "appLog") {"log"}
+
+            def multiPartFile = request.getFile('file')
+
+            InputStreamReader sr = new InputStreamReader(multiPartFile.inputStream)
+            CSVReader reader = new CSVReader(sr)
+
+            // Turn off index mirroring.
+            createDataService.stopSearchableIndex()
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                createDataService.startSearchableIndex() // Start mirroring again and rebuild index.
+                reader.close()
+                result.error = [ code: m.code, args: m.args ]
+                return result
+            }
+
+            if(!multiPartFile || multiPartFile.isEmpty())
+                return fail(code: "default.file.not.supplied")
+
+            if (multiPartFile.getSize() > fileMaxSize)
+                return fail(code: "default.file.over.max.size", args: [fileMaxSize/kByteMultiplier, "kB"])
+
+            def line = []
+            def lineNumber = 0
+            def maxNumberOfColumns = 19
+            def inventoryParams = [:]
+            def inventoryProperties = ["name", "description", "comment", "unitsInStock", "reorderPoint", "reorderQuantity",
+                                                        "unitOfMeasure", "estimatedUnitPriceAmount", "estimatedUnitPriceCurrency",
+                                                        "enableReorderListing", "inventoryLocation", "inventoryStore", "site",
+                                                        "inventoryGroup", "inventoryType",
+                                                        "suppliersPartNumber", "preferredSupplier", "alternateSuppliers",
+                                                        "spareFor"]
+
+            def siteInstance
+            def alternateSupplierInstance
+            def preferredSupplierInstance
+            def supplierTypeInstance
+            def supplierTypeUnknown = SupplierType.get(1)
+            def spareForInstance
+            def inventoryTypeInstance
+            def unitOfMeasureInstance
+            def inventoryGroupInstance
+            def inventoryItemInstance
+            def inventoryStoreInstance
+            def inventoryLocationInstance
+
+            def tempPreferredSupplierItemAndType = ''
+            def tempPreferredSupplierItem = ''
+            def tempPreferredSupplierType = ''
+
+            def tempAlternateSuppliers = []
+            def tempSupplierItem = ''
+            def tempSupplierType = ''
+            def tempSupplierItemAndType = []
+
+            def tempSpareFor = []
+
+            def nextLine = {
+                    line = reader.readNext()
+                    lineNumber ++
+                    log.info "Processing line: " + lineNumber
+            }
+
+            def parseInputList = {
+                if( (it == null) || (it.trim() == '') ) return []
+                return it.split(";").collect{it.trim()}
+            }
+
+            def parseItemAndType = {
+                return it.split("@").collect{it.trim()}
+            }
+
+            // Get first line.
+            nextLine()
+
+            // Check for header line 1.
+            if(line != templateHeaderLine1) {
+                log.error "Failed to find header line 1. "
+                log.error "Required: " + templateHeaderLine1.toString()
+                log.error "Supplied: " + line.toString()
+                return fail(code: "default.file.no.header")
+            }
+
+            log.info "Header line found."
+
+            // Prepare the first body line.
+            nextLine()
+
+            // Primary loop.
+            while(line) {
+
+                if(line.size() > maxNumberOfColumns) {
+                    log.error "Too many columns on line: " + lineNumber
+                    return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                }
+
+                // Ignore comment lines.
+                if(line.toString().toLowerCase().contains("comment")) {
+                    log.info "Comment line found."
+                    nextLine()
+                    continue
+                }
+
+                // Ignore example lines.
+                if(line.toString().toLowerCase().contains("example")) {
+                    log.info "Example line found."
+                    nextLine()
+                    continue
+                }
+
+                // Parse the line into the params map.
+                inventoryParams = [:]
+                line.eachWithIndex { it, j ->
+                    inventoryParams."${inventoryProperties[j]}" = it.trim()
+                }
+
+                // Debug
+                log.debug " Supplied params: "
+                log.debug inventoryParams
+
+                // Ignore blank lines.
+                if(inventoryParams.name == '') {
+                    log.info "No name found."
+                    nextLine()
+                    continue
+                }
+
+                /** Prepare the params and create supporting items as required. */
+
+                // Site
+                inventoryParams.site = WordUtils.capitalize(inventoryParams.site)
+                siteInstance = Site.findByName(inventoryParams.site)
+                if(!siteInstance) {
+                    siteInstance = new Site(name: inventoryParams.site)
+                    if(!siteInstance.save()) {
+                        log.error "Failed to create site on line: " + lineNumber
+                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+
+                // InventoryStore
+                inventoryParams.inventoryStore = WordUtils.capitalizeFully(inventoryParams.inventoryStore)
+                inventoryStoreInstance = InventoryStore.findByName(inventoryParams.inventoryStore)
+                if(!inventoryStoreInstance) {
+                    inventoryStoreInstance = new InventoryStore(name: inventoryParams.inventoryStore,
+                                                                                                site: siteInstance)
+                    if(!inventoryStoreInstance.save()) {
+                        log.error "Failed to create inventory store on line: " + lineNumber
+                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+
+                // InventoryLocation
+                inventoryParams.inventoryLocation = WordUtils.capitalize(inventoryParams.inventoryLocation)
+                inventoryLocationInstance = InventoryLocation.findByName(inventoryParams.inventoryLocation)
+                if(!inventoryLocationInstance) {
+                    inventoryLocationInstance = new InventoryLocation(name: inventoryParams.inventoryLocation,
+                                                                                                        inventoryStore: inventoryStoreInstance)
+                    if(!inventoryLocationInstance.save()) {
+                        log.error "Failed to create inventory location on line: " + lineNumber
+                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+
+                // InventoryGroup
+                inventoryParams.inventoryLocation = WordUtils.capitalizeFully(inventoryParams.inventoryLocation)
+                inventoryGroupInstance = InventoryGroup.findByName(inventoryParams.inventoryGroup)
+                if(!inventoryGroupInstance) {
+                    inventoryGroupInstance = new InventoryGroup(name: inventoryParams.inventoryGroup)
+                    if(!inventoryGroupInstance.save()) {
+                        log.error "Failed to create inventory group on line: " + lineNumber
+                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+
+                // InventoryType
+                inventoryParams.inventoryType = WordUtils.capitalizeFully(inventoryParams.inventoryType)
+                inventoryTypeInstance = InventoryType.findByName(inventoryParams.inventoryType)
+                if(!inventoryTypeInstance) {
+                    inventoryTypeInstance = new InventoryType(name: inventoryParams.inventoryType)
+                    if(!inventoryTypeInstance.save()) {
+                        log.error "Failed to create inventory type on line: " + lineNumber
+                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+
+                // UnitOfMeasure.
+                unitOfMeasureInstance = UnitOfMeasure.findByName(inventoryParams.unitOfMeasure)
+                if(!unitOfMeasureInstance) {
+                    unitOfMeasureInstance = new UnitOfMeasure(name: inventoryParams.unitOfMeasure)
+                    if(!unitOfMeasureInstance.save()) {
+                        log.error "Failed to create unit of measure on line: " + lineNumber
+                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                    }
+                }
+
+                // Preferred Supplier
+                if(inventoryParams.preferredSupplier) {
+                    tempPreferredSupplierItemAndType = parseItemAndType(inventoryParams.preferredSupplier)
+                    tempPreferredSupplierItem = WordUtils.capitalize(tempPreferredSupplierItemAndType[0])
+
+                    preferredSupplierInstance = Supplier.findByName(tempPreferredSupplierItem)
+                    if(!preferredSupplierInstance) {
+
+                        // SupplierType.
+                        if(tempPreferredSupplierItemAndType.size == 2) {
+                            tempPreferredSupplierType = WordUtils.capitalize(tempPreferredSupplierItemAndType[1])
+                            supplierTypeInstance = SupplierType.findByName(tempPreferredSupplierType)
+                        }
+                        else
+                            supplierTypeInstance = supplierTypeUnknown
+                        if(!supplierTypeInstance) {
+                            log.error "Failed to find preferred supplier type on line: " + lineNumber
+                            return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                        }
+
+                        preferredSupplierInstance = new Supplier(name: tempPreferredSupplierItem,
+                                                                                            supplierType: supplierTypeInstance)
+                        if(!preferredSupplierInstance.save()) {
+                            log.error "Failed to create preferred supplier on line: " + lineNumber
+                            return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                        }
+                    }
+                }
+                else
+                    preferredSupplierInstance = null
+
+                // Alternate Suppliers.
+                tempAlternateSuppliers = parseInputList(inventoryParams.alternateSuppliers)
+                inventoryParams.alternateSuppliers = []
+
+                for(tempSupplier in tempAlternateSuppliers) {
+                    tempSupplierItemAndType = parseItemAndType(tempSupplier)
+                    tempSupplierItem = WordUtils.capitalizeFully(tempSupplierItemAndType[0])
+
+                    alternateSupplierInstance = Supplier.findByName(tempSupplierItem)
+                    if(!alternateSupplierInstance) {
+
+                        // SupplierType.
+                        if(tempSupplierItemAndType.size == 2) {
+                            tempSupplierType = WordUtils.capitalize(tempSupplierItemAndType[1])
+                            supplierTypeInstance = SupplierType.findByName(tempSupplierType)
+                        }
+                        else
+                            supplierTypeInstance = supplierTypeUnknown
+                        if(!supplierTypeInstance) {
+                            log.error "Failed to find alternate supplier type on line: " + lineNumber
+                            return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                        }
+
+                        alternateSupplierInstance = new Supplier(name: tempSupplierItem,
+                                                                            supplierType: supplierTypeInstance)
+                        if(!alternateSupplierInstance.save()) {
+                            log.error "Failed to create alternate suppliers on line: " + lineNumber
+                            return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                        }
+                    }
+
+                    inventoryParams.alternateSuppliers.add(alternateSupplierInstance)
+                }
+
+                // spareFor.
+                tempSpareFor = parseInputList(inventoryParams.spareFor)
+                inventoryParams.spareFor = []
+
+                for(asset in tempSpareFor) {
+
+                    asset = WordUtils.capitalize(asset)
+
+                    spareForInstance = Asset.findByName(asset)
+                    if(!spareForInstance) {
+                        log.error "Failed to find 'Spare For' asset on line: " + lineNumber
+                        return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                    }
+
+                    inventoryParams.spareFor.add(spareForInstance)
+                }
+
+                // Assign the retrieved or created instances to params.
+                inventoryParams.inventoryLocation = inventoryLocationInstance
+                inventoryParams.inventoryGroup = inventoryGroupInstance
+                inventoryParams.inventoryType = inventoryTypeInstance
+                inventoryParams.unitOfMeasure = unitOfMeasureInstance
+                inventoryParams.preferredSupplier = preferredSupplierInstance
+
+                // Name.
+                // Checked above for blank string.
+                inventoryParams.name = WordUtils.capitalize(inventoryParams.name)
+
+                // Description.
+                if(inventoryParams.description != '')
+                    inventoryParams.description = inventoryParams.description[0].toUpperCase() + inventoryParams.description[1..-1]
+
+                // Debug
+                log.debug "InventoryParams: "
+                log.debug inventoryParams
+
+                // Create new or update.
+                inventoryItemInstance = InventoryItem.findByName(inventoryParams.name)
+                if(inventoryItemInstance) {
+                    log.info "Updating existing item: " + inventoryItemInstance
+                    inventoryItemInstance.properties = inventoryParams
+                }
+                else {
+                    log.info "Creating new item: " + inventoryParams.name
+                    inventoryItemInstance = new InventoryItem(inventoryParams)
+                }
+
+                // Save inventoryItem.
+                if(inventoryItemInstance.hasErrors() || !inventoryItemInstance.save()) {
+                    log.error "Failed to create item on line: " + lineNumber
+                    log.debug inventoryItemInstance.errors
+                    return fail(code: "inventory.import.failure", args: [lineNumber, logFileLink])
+                }
+
+                if(lineNumber % 100 == 0)
+                    cleanUpGorm()
+
+                if(!result.error) nextLine()
+            } //while(line)
+
+            // Success.
+            log.info "End of file."
+            createDataService.startSearchableIndex() // Start mirroring again and rebuild index.
+            reader.close()
+            return result
+
+        } //end withTransaction
+    } // end importInventory()
+
+    /**
+    * Build an inventory template csv file.
+    * This template can then be populated for import.
+    * @returns The template as a String in csv format.
+    */
+    def buildInventoryTemplate() {
+
+        StringWriter sw = new StringWriter()
+        CSVWriter writer = new CSVWriter(sw)
+
+        writeTemplateLines(writer)
+
+        writer.close()
+        return sw.toString()
+    }
+
+    private writeTemplateLines(writer) {
+        writer.writeNext(templateHeaderLine1 as String[])
+        writer.writeNext()
+        writer.writeNext("Comment: The header line is required.")
+        writer.writeNext("Comment: Required columns are marked with a (*) in the header line.")
+        writer.writeNext("Comment: Lists of items in a column must be separated by a semicolon (;), not a comma.")
+        writer.writeNext("Comment: The at symbol (@) is reserved for indicating supplier types.")
+        writer.writeNext("Comment: Identical and existing names will be considered as the same item.")
+        writer.writeNext("Comment: Lines containing 'comment' will be ignored.")
+        writer.writeNext("Comment: Lines containing 'example' will be ignored.")
+        writer.writeNext("Comment: This file must be saved as a CSV file before import.")
+        writer.writeNext()
+    }
+
+    /**
+    * Build an inventory example/test file.
+    * This test file can be imported to test the import and export methods.
+    * @returns The test file as a String in csv format.
+    */
+    def buildInventoryExample() {
+
+        StringWriter sw = new StringWriter()
+        CSVWriter writer = new CSVWriter(sw)
+
+        writeTemplateLines(writer)
+
+        // Requires creation of some of the base/group/type data.
+        writer.writeNext(["Split19", "19mm split pin", "Very usefull item.",
+                                        "1024", "0", "1",
+                                        "each", "5", "NZD",
+                                        "false", "BR4",
+                                        "Store #99", "Inventory Depot",
+                                        "Mechanical Stock",
+                                        "Consumable",
+                                        "123", "Multi Supplier@Local",
+                                        "Multi Distributors1@OEM; Multi Distributors2@Local",
+                                        ""
+                                        ] as String[])
+
+        // Using existing base data.
+        writer.writeNext(["2204E-2RS", "Double Row Self Align Ball Bearing 2204E-2RS - Sealed - 20/47x18", "",
+                                        "4", "1", "9",
+                                        "each", "16.35", "USD",
+                                        "TRUE", "BR4",
+                                        "Store #99", "Inventory Depot",
+                                        "Mechanical Stock",
+                                        "Consumable",
+                                        "456KL", "Multi Supplier",
+                                        "Multi Distributors1; Multi Distributors2",
+                                        ""
+                                        ] as String[])
+
+        writer.close()
+        return sw.toString()
+    }
+
+    /**
+    * Build complete inventory for export.
+    * @param inventoryItemList The list of inventory items to build.
+    * @returns The inventory as a String in csv format.
+    */
+    def buildInventory(List inventoryItemList) {
+
+        def sw = new StringWriter()
+        def writer = new CSVWriter(sw)
+
+        writeTemplateLines(writer)
+
+        //Rows
+        def row
+
+        inventoryItemList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }.each() { inventoryItem ->
+            row = []
+            row.add(inventoryItem.name)
+            row.add(inventoryItem.description)
+            row.add(inventoryItem.comment)
+            row.add(inventoryItem.unitsInStock)
+            row.add(inventoryItem.reorderPoint)
+            row.add(inventoryItem.reorderQuantity)
+            row.add(inventoryItem.unitOfMeasure)
+            row.add(inventoryItem.estimatedUnitPriceAmount)
+            row.add(inventoryItem.estimatedUnitPriceCurrency)
+            row.add(inventoryItem.enableReorderListing)
+            row.add(inventoryItem.inventoryLocation)
+            row.add(inventoryItem.inventoryLocation.inventoryStore)
+            row.add(inventoryItem.inventoryLocation.inventoryStore.site)
+            row.add(inventoryItem.inventoryGroup)
+            row.add(inventoryItem.inventoryType)
+            row.add(inventoryItem.suppliersPartNumber)
+
+            if(inventoryItem.preferredSupplier)
+                row.add( inventoryItem.preferredSupplier.name + "@" + inventoryItem.preferredSupplier.supplierType )
+            else
+                row.add('')
+
+            row.add( inventoryItem.alternateSuppliers.sort { p1, p2 ->
+                p1.name.compareToIgnoreCase(p2.name)
+            }.collect { it.name + "@" + it.supplierType }.join(';') )
+
+            row.add(inventoryItem.spareFor.sort { p1, p2 ->
+                p1.name.compareToIgnoreCase(p2.name)
+            }.collect { it.name }.join(';'))
+
+            writer.writeNext(row as String[])
+        }
+
+        writer.close()
+        return sw.toString()
+    } // end buildInventory()
+
+    /**
+    * Import inventoryItemPurchases creating items as required.
+    */
+    def importInventoryItemPurchases(request) {
+        InventoryItemPurchase.withTransaction { status ->
+            def result = [:]
+
+            def kByteMultiplier = 1000
+            def fileMaxSize = 800 * kByteMultiplier
+            def logFileLink = g.link(controller: "appCore", action: "appLog") {"log"}
+
+            def multiPartFile = request.getFile('file')
+
+            InputStreamReader sr = new InputStreamReader(multiPartFile.inputStream)
+            CSVReader reader = new CSVReader(sr)
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                reader.close()
+                result.error = [ code: m.code, args: m.args ]
+                return result
+            }
+
+            if(!multiPartFile || multiPartFile.isEmpty())
+                return fail(code: "default.file.not.supplied")
+
+            if (multiPartFile.getSize() > fileMaxSize)
+                return fail(code: "default.file.over.max.size", args: [fileMaxSize/kByteMultiplier, "kB"])
+
+            def line = []
+            def lineNumber = 0
+            def maxNumberOfColumns = 10
+            def inventoryItemPurchaseParams = [:]
+            def inventoryItemPurchaseProperties = ["inventoryItem", "purchaseOrderNumber", "quantity",
+                                                                                "inventoryItemPurchaseType",
+                                                                                "costCode", "enteredBy", "dateEntered",
+                                                                                "orderValueAmount", "orderValueCurrency", "invoiceNumber"]
+
+            def personInstance
+            def costCodeInstance
+            def inventoryItemInstance
+            def inventoryItemPurchaseInstance
+            def inventoryItemPurchaseTypeInstance
+
+            def nextLine = {
+                    line = reader.readNext()
+                    lineNumber ++
+                    log.info "Processing line: " + lineNumber
+            }
+
+            def parseInputDate = {
+                if( (it == null) || (it.trim() == '') ) {
+                    log.error "Failed to find any date on line: " + lineNumber
+                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
+                }
+
+                def d = it.split("/").collect{it.trim()}
+                if(d.size() != 3) {
+                    log.error "Failed to find full date on line: " + lineNumber
+                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
+                }
+                dateUtilService.makeDate(d[0], d[1], d[2])
+            }
+
+            // Get first line.
+            nextLine()
+
+            // Check for header line 1.
+            if(line != purchasesTemplateHeaderLine1) {
+                log.error "Failed to find header line 1. "
+                log.error "Required: " + purchasesTemplateHeaderLine1.toString()
+                log.error "Supplied: " + line.toString()
+                return fail(code: "default.file.no.header")
+            }
+
+            log.info "Header line found."
+
+            // Prepare the first body line.
+            nextLine()
+
+            // Primary loop.
+            while(line) {
+
+                if(line.size() > maxNumberOfColumns) {
+                    log.error "Too many columns on line: " + lineNumber
+                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
+                }
+
+                // Ignore comment lines.
+                if(line.toString().toLowerCase().contains("comment")) {
+                    log.info "Comment line found."
+                    nextLine()
+                    continue
+                }
+
+                // Ignore example lines.
+                if(line.toString().toLowerCase().contains("example")) {
+                    log.info "Example line found."
+                    nextLine()
+                    continue
+                }
+
+                // Parse the line into the params map.
+                inventoryItemPurchaseParams = [:]
+                line.eachWithIndex { it, j ->
+                    inventoryItemPurchaseParams."${inventoryItemPurchaseProperties[j]}" = it.trim()
+                }
+
+                // Debug
+                log.debug " Supplied params: "
+                log.debug inventoryItemPurchaseParams
+
+                // Ignore blank lines.
+                if(inventoryItemPurchaseParams.inventoryItem == '') {
+                    log.info "No inventory item name found."
+                    nextLine()
+                    continue
+                }
+
+                // Inventory Item.
+                inventoryItemPurchaseParams.inventoryItem = WordUtils.capitalize(inventoryItemPurchaseParams.inventoryItem)
+                inventoryItemInstance = InventoryItem.findByName(inventoryItemPurchaseParams.inventoryItem)
+                if(!inventoryItemInstance) {
+                    log.error "Inventory item not found on line: " + lineNumber
+                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
+                }
+                inventoryItemPurchaseParams.inventoryItem = inventoryItemInstance
+
+                // Quantity.
+                if(inventoryItemPurchaseParams.quantity.isInteger())
+                    inventoryItemPurchaseParams.quantity = inventoryItemPurchaseParams.quantity.toInteger()
+                else {
+                    log.error "Quantity is not a valid number on line: " + lineNumber
+                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
+                }
+
+                // InventoryItemPurchaseType.
+                inventoryItemPurchaseParams.inventoryItemPurchaseType = WordUtils.capitalizeFully(inventoryItemPurchaseParams.inventoryItemPurchaseType)
+                inventoryItemPurchaseTypeInstance = InventoryItemPurchaseType.findByName(inventoryItemPurchaseParams.inventoryItemPurchaseType)
+                if(!inventoryItemPurchaseTypeInstance) {
+                    log.error "Inventory item purchase type not found on line: " + lineNumber
+                    log.debug inventoryItemPurchaseParams.inventoryItemPurchaseType
+                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
+                }
+                inventoryItemPurchaseParams.inventoryItemPurchaseType = inventoryItemPurchaseTypeInstance
+
+                // CostCode.
+                if(inventoryItemPurchaseParams.costCode != '') {
+                    inventoryItemPurchaseParams.costCode = WordUtils.capitalizeFully(inventoryItemPurchaseParams.costCode)
+                    costCodeInstance = CostCode.findByName(inventoryItemPurchaseParams.costCode)
+                    if(!costCodeInstance) {
+                        costCodeInstance = new CostCode(name: inventoryItemPurchaseParams.costCode)
+                        if(!costCodeInstance.save()) {
+                            log.error "Failed to create cost code on line: " + lineNumber
+                            return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
+                        }
+                    }
+                    inventoryItemPurchaseParams.costCode = costCodeInstance
+                }
+
+                // Entered By.
+                inventoryItemPurchaseParams.enteredBy = inventoryItemPurchaseParams.enteredBy.toLowerCase()
+                personInstance = Person.findByLoginName(inventoryItemPurchaseParams.enteredBy)
+                if(!personInstance) {
+                    log.error "Entered by person not found on line: " + lineNumber
+                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
+                }
+                inventoryItemPurchaseParams.enteredBy = personInstance
+
+                // Date Entered.
+                inventoryItemPurchaseParams.dateEntered = parseInputDate(inventoryItemPurchaseParams.dateEntered)
+
+                // Debug
+                log.debug "InventoryItemPurchaseParams: "
+                log.debug inventoryItemPurchaseParams
+
+                // Save inventoryItem.
+                log.info "Creating new purchase."
+                inventoryItemPurchaseInstance = new InventoryItemPurchase(inventoryItemPurchaseParams)
+
+                if(inventoryItemPurchaseInstance.hasErrors() || !inventoryItemPurchaseInstance.save()) {
+                    log.error "Failed to create item on line: " + lineNumber
+                    log.debug inventoryItemPurchaseInstance.errors
+                    return fail(code: "inventoryItemPurchase.import.failure", args: [lineNumber, logFileLink])
+                }
+
+                if(lineNumber % 100 == 0)
+                    cleanUpGorm()
+
+                if(!result.error) nextLine()
+            } //while(line)
+
+            // Success.
+            log.info "End of file."
+            reader.close()
+            return result
+
+
+         } //end withTransaction
+    } // end importInventoryItemPurchases()
+
+    private getTemplateHeaderLine1() {
+            ["Name*", "Description", "Comment", "Units In Stock", "Reorder Point*", "Reorder Quantity", "Unit Of Measure*",
+            "Estimated Unit Price", "Currency", "Enable Reorder", "Location*", "Store*", "Site*", "Group*", "Type*",
+            "Supplier's Part Number", "Preferred Supplier", "Alternate Suppliers",
+            "Spare For"]
+    }
+
+    private getPurchasesTemplateHeaderLine1() {
+            ["Inventory Item*", "Purchase Order Number*", "Quantity*", "Purchase Type*", "Cost Code*", "Entered By*",
+            "Date Entered*", "Order Value", "Currency", "Invoice Number"]
+    }
+
+    /**
+    * This cleans up the hibernate session and a grails map.
+    * For more info see: http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/
+    * The hibernate session flush is normal for hibernate.
+    * The map is apparently used by grails for domain object validation errors.
+    * A starting point for clean up is every 100 objects.
+    */
+    def cleanUpGorm() {
+        def session = sessionFactory.currentSession
+        session.flush()
+        session.clear()
+        propertyInstanceMap.get().clear()
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/InventoryItemSearchService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/InventoryItemSearchService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/InventoryItemSearchService.groovy	(revision 753)
@@ -0,0 +1,368 @@
+import net.kromhouts.HqlBuilder
+import grails.orm.PagedResultList
+import org.compass.core.engine.SearchEngineQueryParseException
+
+/**
+* Service class that encapsulates the business logic for InventoryItem searches.
+*/
+class InventoryItemSearchService {
+
+    boolean transactional = false
+
+    def dateUtilService
+    def messageSource
+
+    def paramsMax = 100000
+
+    /**
+    * Selects and returns the correct search results based on the supplied quickSearch.
+    * @param params The request params, may contain params.quickSearch string to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getQuickSearch(params, locale) {
+        def result = [:]
+        result.quickSearch = params.quickSearch ?: "all"
+
+        def getMessage = { Map m ->
+            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
+        }
+
+        switch (result.quickSearch) {
+            case "inventoryBelowReorder":
+                result.inventoryItemList = getInventoryBelowReorder(params)
+                if(result.inventoryItemList.totalCount > 0)
+                    result.message = getMessage(code:"inventoryItem.search.text.below.reorder.description")
+                else
+                    result.message = getMessage(code:"inventoryItem.search.text.below.reorder.none.found")
+                break
+            case "inventoryBelowReorderAll":
+                result.inventoryItemList = getInventoryBelowReorder(params, false)
+                if(result.inventoryItemList.totalCount > 0)
+                    result.message = getMessage(code:"inventoryItem.search.text.below.reorder.all.description")
+                else
+                    result.message = getMessage(code:"inventoryItem.search.text.below.reorder.none.found")
+                break
+            case "recentlyUsed":
+                result.daysBack = params.daysBack?.isInteger() ? params.daysBack.toInteger() : 14
+                result.inventoryItemList = getRecentlyUsed(params, result.daysBack)
+                if(result.inventoryItemList.totalCount > 0)
+                    result.message = getMessage(code:"inventoryItem.search.text.recently.used.description", args:[result.daysBack])
+                else
+                    result.message = getMessage(code:"inventoryItem.search.text.recently.used.none.found", args:[result.daysBack])
+                break
+            default:
+                result.inventoryItemList = getAll(params)
+                if(result.inventoryItemList.totalCount > 0)
+                    result.message = getMessage(code:"inventoryItem.search.text.all.description")
+                else
+                    result.message = getMessage(code:"inventoryItem.search.text.all.none.found")
+                break
+        } // switch.
+
+        // Success.
+        return result
+
+    } // getQuickSearch
+
+    /**
+    * Get all inventory items.
+    * @param params The request params.
+    */
+    def getAll(params) {
+        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
+        params.offset = params?.offset?.toInteger() ?: 0
+        params.sort = params?.sort ?: "name"
+        params.order = params?.order ?: "asc"
+
+        def inventoryItemList = InventoryItem.createCriteria().list(
+            max: params.max,
+            offset: params.offset,
+            sort: params.sort,
+            order: params.order) {
+            } // createCriteria
+    } // getAll
+
+    /**
+    * List inventory items that are below reorder point.
+    * @param params The request params.
+    * @param onlyReorderEnabled Only include items with reorder enabled, defaults to true.
+    */
+    def getInventoryBelowReorder(params, onlyReorderEnabled=true) {
+        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
+        params.offset = params?.offset?.toInteger() ?: 0
+        params.sort = params?.sort ?: "name"
+        params.order = params?.order ?: "asc"
+
+        def inventoryItemList = InventoryItem.createCriteria().list(
+            max: params.max,
+            offset: params.offset,
+            sort: params.sort,
+            order: params.order) {
+                eq("isActive", true)
+                if(onlyReorderEnabled)
+                    eq("enableReorderListing", true)
+                leProperty("unitsInStock", "reorderPoint")
+            } // createCriteria
+    } // getInventoryBelowReorder
+
+    /**
+    * Search for inventory items that are below reorder point.
+    * @param params The request params.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getReorderSearch(params, locale) {
+        def result = [:]
+
+        def getMessage = { Map m ->
+            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
+        }
+
+        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
+        params.offset = params?.offset?.toInteger() ?: 0
+
+        def sort = "inventoryItem." + (params?.sort ?: "name")
+        def order = params?.order == "desc" ? "desc" : "asc"
+
+        def q = new HqlBuilder(max: params.max, offset: params.offset).query {
+            select 'count(distinct inventoryItem) as inventoryItemCount'
+            from 'InventoryItem as inventoryItem',
+                    'left join inventoryItem.alternateSuppliers as alternateSupplier'
+            where 'inventoryItem.unitsInStock <= inventoryItem.reorderPoint'
+                    and 'inventoryItem.isActive = true'
+                    and 'inventoryItem.isObsolete = false'
+
+                    if(!params.includeReorderListingDisabled)
+                        and "inventoryItem.enableReorderListing = true"
+
+                    if(params.selectedSupplier?.isLong()) {
+                        namedParams.supplier = Supplier.get(params.selectedSupplier.toLong())
+                        if(params.includeAlternateSuppliers)
+                            and "(inventoryItem.preferredSupplier = :supplier or alternateSupplier = :supplier)"
+                        else
+                            and "inventoryItem.preferredSupplier = :supplier"
+                    } // if selectedSupplier
+
+                    if(params.selectedGroups) {
+                        namedParams.selectedGroupIds = params.selectedGroups
+                        and  "inventoryItem.inventoryGroup.id in(:selectedGroupIds)"
+                    }
+
+                    if(!params.includeOnBackOrder) {
+                        // Subquery!
+                        def onBackOrder = new HqlBuilder().query {
+                            from "InventoryItemPurchase p"
+                            where "p.inventoryItem = inventoryItem"
+                                    and "p.inventoryItem = inventoryItem"
+                                    and "p.inventoryItemPurchaseType.id = 1" // Order Placed.
+                                    and "p.receivedComplete = false"
+                                    and "p.date > :oneMonthAgo"
+                        }
+
+                        namedParams.oneMonthAgo = new Date() - 30
+                        and "not exists ($onBackOrder.query)"
+                    }
+
+        } // query
+
+        def totalCount = InventoryItem.executeQuery(q.query, q.namedParams)[0].toInteger()
+
+        q.select = 'distinct inventoryItem'
+        q.order = "by $sort $order, inventoryItem.id asc"
+        def list = InventoryItem.executeQuery(q.query, q.namedParams, q.paginateParams)
+
+        result.inventoryItemList = new PagedResultList(list, totalCount)
+
+        // Get the result message.
+        if(result.inventoryItemList.totalCount > 0)
+            result.message = getMessage(code:"inventoryItem.search.text.below.reorder.description")
+        else
+            result.message = getMessage(code:"inventoryItem.search.text.below.reorder.none.found")
+
+        // Success.
+        return result
+
+    } // getReorderSearch
+
+    /**
+    * Get a list of recently used inventory items.
+    * @param params The request params.
+    * @param daysBack The number of days back to get results for.
+    */
+    def getRecentlyUsed(params, daysBack) {
+        def paginateParams = [:]
+        paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
+        paginateParams.offset = params?.offset?.toInteger() ?: 0
+
+        def sort = "inventoryItem." + (params?.sort ?: "name")
+        def order = params?.order == "desc" ? "desc" : "asc"
+        def orderBy = " order by " + sort + ' ' + order
+
+        def namedParams = [:]
+        namedParams.startOfDay = dateUtilService.today - daysBack
+
+        def baseQuery = "from InventoryItem as inventoryItem \
+                                        left join inventoryItem.inventoryMovements as inventoryMovement \
+                                        where (inventoryItem.isActive = true \
+                                                    and inventoryMovement.date > :startOfDay \
+                                                    and inventoryMovement.inventoryMovementType = 1 \
+                                                    )"
+
+        def searchQuery = "select distinct inventoryItem " + baseQuery + orderBy
+        def list = InventoryItem.executeQuery(searchQuery, namedParams, paginateParams)
+
+        def countQuery = "select count(distinct inventoryItem) as inventoryItemCount " + baseQuery
+        def totalCount = InventoryItem.executeQuery(countQuery, namedParams)[0].toInteger()
+
+        def inventoryItemInstanceList = new PagedResultList(list, totalCount)
+        return inventoryItemInstanceList
+    } // getRecentlyUsed
+
+    /**
+    * Get a list of inventory items by search text.
+    * @param params The request params.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getTextSearch(params, locale) {
+        def result = [:]
+        result.searchText = params.searchText.trim() ?: "" // User supplied text.
+        result.queryString = "" // Modified string that will be passed to searchable query.
+
+        def getMessage = { Map m ->
+            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
+        }
+
+        params.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
+        params.offset = params?.offset?.toInteger() ?: 0
+        params.sort = params?.sort ?: "id"
+        params.order = params?.order ?: "asc"
+
+        // Build searchableParams.
+        // Do not include params.sort, since not all properites are indexed.
+        def searchableParams = [:]
+        searchableParams.max = params.max
+        searchableParams.offset = params.offset
+        searchableParams.reload = true
+        searchableParams.defaultOperator =  'or'
+        def properitesList = []
+        if(params.searchName)
+            properitesList << '$/InventoryItem/name'
+        if(params.searchDescription)
+            properitesList << '$/InventoryItem/description'
+        if(params.searchComment)
+            properitesList << '$/InventoryItem/comment'
+        if(params.searchLocation)
+            properitesList << '$/InventoryItem/inventoryLocation/name'
+        if(params.searchGroup)
+            properitesList << '$/InventoryItem/inventoryGroup/name'
+        if(params.searchSpareFor) {
+            properitesList << '$/InventoryItem/spareFor/name'
+            properitesList << '$/InventoryItem/spareFor/description'
+            properitesList << '$/InventoryItem/spareFor/comment'
+        }
+        if(properitesList)
+            searchableParams.properties = properitesList
+
+        // Check searchText for key words and modifiers.
+        def hasIsActive = result.searchText.contains('isActive')
+        def hasIsObsolete = result.searchText.contains('isObsolete')
+        def hasBracket = result.searchText.contains('(') || result.searchText.contains(')')
+        def containsModifier = { s ->
+            s.contains('"') ||
+            s.contains('~') ||
+            s.contains('*') ||
+            s.contains('(') ||
+            s.contains(')') ||
+            s.contains('+') ||
+            s.contains('-') ||
+            s.contains('^') ||
+            s.contains('OR') ||
+            s.contains('AND') ||
+            s.contains('NOT') ||
+            s.contains('TO') ||
+            s.contains('isObsolete') ||
+            s.contains('isActive')
+        }
+
+        // Expand search with wildcards.
+        def addWildcards = { text ->
+            text = text.tokenize().collect { token ->
+                if(!containsModifier(token))
+                    '*'+token+'*'
+                else
+                    token
+            }.join(' ')
+            return text
+        }
+
+        // Default isActive and isObsolete.
+        def addDefaultFlags = { text ->
+            if(!hasBracket)
+                text = '( '+text+' )'
+            if(!hasIsActive)
+                text = text + ' AND isActive:"true" '
+            if(!hasIsObsolete)
+                text = text + ' AND isObsolete:"false" '
+            return text
+        }
+
+        result.queryString = addWildcards(result.searchText)
+        result.queryString = addDefaultFlags(result.queryString)
+
+        // Perform the searchable query.
+        try {
+            result.inventoryItemList = InventoryItem.search(result.queryString, searchableParams)
+
+            // Would be nice if this worked.
+//             result.inventoryItemList = InventoryItem.search(result.searchText, searchableParams) {
+//                 must(term("isActive", true))
+//                 must(term("isObsolete", false))
+//             }
+
+        } catch (e) {
+            log.error e
+            result.inventoryItemList = [:]
+            result.inventoryItemList.results = []
+            result.inventoryItemList.total = 0
+        }
+
+        // Sort the returned instances.
+        if(params.sort != 'id') {
+            if(params.order == 'asc') {
+                if(params.sort == 'name' || params.sort == 'description')
+                    result.inventoryItemList.results.sort { p1, p2 -> p1[params.sort].compareToIgnoreCase(p2[params.sort]) }
+                else if(params.sort == 'inventoryGroup') {
+                    result.inventoryItemList.results.sort { p1, p2 ->
+                        p1.inventoryGroup.name.compareToIgnoreCase(p2.inventoryGroup.name)
+                    }
+                }
+                else if(params.sort == 'unitsInStock')
+                    result.inventoryItemList.results.sort {p1, p2 -> p1[params.sort]  <=> p2[params.sort] }
+            } // asc.
+            else {
+                if(params.sort == 'name' || params.sort == 'description')
+                    result.inventoryItemList.results.sort { p1, p2 -> p2[params.sort].compareToIgnoreCase(p1[params.sort]) }
+                else if(params.sort == 'inventoryGroup') {
+                    result.inventoryItemList.results.sort { p1, p2 ->
+                        p2.inventoryGroup.name.compareToIgnoreCase(p1.inventoryGroup.name)
+                    }
+                }
+                else if(params.sort == 'unitsInStock')
+                    result.inventoryItemList.results.sort {p1, p2 -> p2[params.sort] <=> p1[params.sort]}
+            } // desc.
+        } // sort.
+
+        // Create a PagedResultList.
+        result.inventoryItemList = new PagedResultList(result.inventoryItemList.results, result.inventoryItemList.total)
+
+        // Get the result message.
+        if(result.inventoryItemList.totalCount > 0)
+            result.message = getMessage(code:"inventoryItem.search.text.found", args: [result.queryString])
+        else
+            result.message = getMessage(code:"inventoryItem.search.text.none.found", args: [result.queryString])
+
+        // Success.
+        return result
+
+    } // getTextSearch()
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/InventoryItemService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/InventoryItemService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/InventoryItemService.groovy	(revision 753)
@@ -0,0 +1,482 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+import org.apache.commons.lang.WordUtils
+
+/**
+* Provides a service class for the InventoryItem domain class.
+*/
+class InventoryItemService {
+
+    boolean transactional = false
+
+    def createDataService
+
+    def sessionFactory
+    def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP
+
+    /**
+    * Prepare the data for the show view.
+    * The result can be used to easily construct the model for the show view.
+    * @param params The incoming params as normally passed to the show view
+    * primarily including the id of the inventoryItem.
+    * @returns A map containing result.error, if any error, otherwise result.inventoryItemInstance.
+    */
+    def show(params) {
+        def result = [:]
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
+            return result
+        }
+
+        result.inventoryItemInstance = InventoryItem.get( params.id )
+
+        if(!result.inventoryItemInstance)
+            return fail(code:"default.not.found")
+
+        def p = [:]
+
+        if(params.paginate == "purchases") {
+            params.showTab = "showPurchasingTab"
+            p.max = Math.min(params.max?.toInteger() ?: 10, 100)
+            p.offset = params.offset?.toInteger() ?: 0
+            p.sort = params.sort ?: null
+            p.order = params.order ?: null
+        }
+        else {
+            p.max = 10
+            p.offset = 0
+        }
+
+        result.inventoryItemPurchasesTotal = InventoryItemPurchase.countByInventoryItem(result.inventoryItemInstance)
+
+        result.inventoryItemPurchases = InventoryItemPurchase.withCriteria {
+                eq("inventoryItem", result.inventoryItemInstance)
+                maxResults(p.max)
+                firstResult(p.offset)
+                // Sorting:
+                // Default is to sort by order number then id.
+                // When a sortable column is clicked then we sort by that.
+                // If the sortable column clicked is order number then we add id as the second sort.
+                if(p.sort && p.order) {
+                    order(p.sort, p.order)
+                    if(p.sort == "purchaseOrderNumber") order('id', 'asc')
+                }
+                else {
+                    order('purchaseOrderNumber', 'desc')
+                    order('id', 'asc')
+                }
+            }
+
+        result.showTab = [:]
+        switch (params.showTab) {
+            case "showMovementTab":
+                result.showTab.movement =  new String("true")
+                break
+            case "showPurchasingTab":
+                result.showTab.purchasing =  new String("true")
+                break
+            default:
+                result.showTab.inventory = new String("true")
+        }
+
+        p.max = result.inventoryMovementListMax = 10
+        p.offset = 0
+        p.order = "desc"
+        p.sort = "id"
+        result.inventoryMovementList = InventoryMovement.findAllByInventoryItem(result.inventoryItemInstance, p)
+        result.inventoryMovementListTotal = InventoryMovement.countByInventoryItem(result.inventoryItemInstance)
+
+
+        // Success.
+        return result
+
+    } // end show()
+
+    def delete(params) {
+        InventoryItem.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryItemInstance && m.field)
+                    result.inventoryItemInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
+                return result
+            }
+
+            result.inventoryItemInstance = InventoryItem.get(params.id)
+
+            if(!result.inventoryItemInstance)
+                return fail(code:"default.not.found")
+
+            if(result.inventoryItemInstance.inventoryMovements)
+                return fail(code:"inventoryMovement.still.associated")
+
+            try {
+                result.inventoryItemInstance.delete(flush:true)
+                return result //Success.
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                return fail(code:"default.delete.failure")
+            }
+
+        } //end withTransaction
+    } // end delete()
+
+    def edit(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
+            return result
+        }
+
+        result.inventoryItemInstance = InventoryItem.get(params.id)
+
+        if(!result.inventoryItemInstance)
+            return fail(code:"default.not.found")
+
+        // Success.
+        return result
+    }
+
+    def update(params) {
+        InventoryItem.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryItemInstance && m.field)
+                    result.inventoryItemInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
+                return result
+            }
+
+            result.inventoryItemInstance = InventoryItem.get(params.id)
+
+            if(!result.inventoryItemInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.inventoryItemInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            result.inventoryItemInstance.properties = params
+            result.inventoryItemInstance.setAlternateSuppliersFromCheckBoxList(params.alternateSuppliers)
+            result.inventoryItemInstance.setSpareForFromCheckBoxList(params.spareFor)
+
+            // Fetch to prevent lazy initialization error.
+            result.inventoryItemInstance.unitOfMeasure
+
+            if(result.inventoryItemInstance.hasErrors() || !result.inventoryItemInstance.save())
+                return fail(code:"default.update.failure")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end update()
+
+    def create(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
+            return result
+        }
+
+        result.inventoryItemInstance = new InventoryItem()
+        result.inventoryItemInstance.properties = params
+
+        // success
+        return result
+    }
+
+    def save(params) {
+        InventoryItem.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryItemInstance && m.field)
+                    result.inventoryItemInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
+                return result
+            }
+
+            result.inventoryItemInstance = new InventoryItem(params)
+            result.inventoryItemInstance.setAlternateSuppliersFromCheckBoxList(params.alternateSuppliers)
+            result.inventoryItemInstance.setSpareForFromCheckBoxList(params.spareFor)
+
+            if(result.inventoryItemInstance.hasErrors() || !result.inventoryItemInstance.save())
+                return fail(code:"default.create.failure")
+
+            // success
+            return result
+
+        } //end withTransaction
+    }
+
+    /**
+    * Save an inventory item picture.
+    * @param params An object or map containing at least the inventoryItem ID.
+    * @param pictureSource A supported source to get the picture image from.
+    * Supported sources:
+    * HttpServletRequest e.g: 'request' var from controller to run getFile('file') against.
+    * ServletContextResource e.g: grailsApplication.mainContext.getResource('images/logo.png')
+    * File e.g: new File('picture.jpg')
+    */
+    def savePicture(params, pictureSource) {
+        InventoryItem.withTransaction { status ->
+            def result = [:]
+
+            def kByteMultiplier = 1000
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryItemInstance && m.field)
+                    result.inventoryItemInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: m.args ?: ["InventoryItem", params.id] ]
+                return result
+            }
+
+            result.inventoryItemInstance = InventoryItem.get(params.id)
+
+            if(!result.inventoryItemInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.inventoryItemInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            if(result.inventoryItemInstance.picture)
+                return fail(field:"picture", code:"inventory.item.already.has.picture")
+
+            // Declare some more variables, since we appear to have most of what we need.
+            def picture = new Picture(inventoryItem: result.inventoryItemInstance)
+            def imaging = new Imaging()
+            def images = null
+            def pictureFile
+            def pictureFileName = ''
+            def pictureInputStream
+
+            // Check the supplied pictureSource and get the inputStream.
+            if(pictureSource instanceof javax.servlet.http.HttpServletRequest) {
+                def multiPartFile = pictureSource.getFile('file')
+                pictureFileName = multiPartFile.originalFilename
+
+                if(!multiPartFile || multiPartFile.isEmpty())
+                    return fail(code: "default.file.not.supplied")
+
+                if (multiPartFile.getSize() > Image.MAX_SIZE)
+                    return fail(code: "default.file.over.max.size", args: [Image.MAX_SIZE/kByteMultiplier, "kB"])
+
+                pictureInputStream = multiPartFile.inputStream
+            }
+            else if(pictureSource instanceof org.springframework.web.context.support.ServletContextResource) {
+                pictureFile = pictureSource.getFile()
+                pictureFileName = pictureFile.name
+
+                if ( !pictureFile.isFile() || (pictureFile.length() == 0) )
+                    return fail(code:"default.file.not.supplied")
+
+                if (pictureFile.length() > Image.MAX_SIZE)
+                    return fail(code:"default.file.over.max.size", args: [Image.MAX_SIZE/kByteMultiplier, "kB"])
+
+                pictureInputStream = pictureSource.inputStream
+            }
+            else if(pictureSource instanceof File) {
+                pictureFile = pictureSource
+                pictureFileName = pictureFile.name
+
+                if ( !pictureFile.isFile() || (pictureFile.length() == 0) )
+                    return fail(code:"default.file.not.supplied")
+
+                if (pictureFile.length() > Image.MAX_SIZE)
+                    return fail(code:"default.file.over.max.size", args: [Image.MAX_SIZE/kByteMultiplier, "kB"])
+
+                pictureInputStream = new FileInputStream(pictureSource)
+            }
+            else {
+                    return fail(code:"inventory.item.picture.source.not.supported")
+            }
+
+            // Create the Images.
+            try {
+                images = imaging.createAll(result.inventoryItemInstance, picture, pictureInputStream)
+                // Ensure the stream is closed.
+                pictureInputStream.close()
+            }
+            catch(Exception ex) {
+                log.error("picture save", ex)
+                // Ensure the stream is closed.
+                pictureInputStream.close()
+                return fail(code:"inventory.item.picture.file.unrecognised", args: [pictureFileName])
+            }
+
+            // Add images to picture.
+            images.each { image ->
+                picture.addToImages(image)
+            }
+
+            // Save picture.
+            if(picture.hasErrors() || !picture.save())
+                return fail(code:"default.create.failure", args: ["Picture"])
+
+            result.inventoryItemInstance.picture = picture
+
+            // Save inventoryItem.
+            if(result.inventoryItemInstance.hasErrors() || !result.inventoryItemInstance.save())
+                return fail(code:"default.create.failure")
+
+            // success
+            return result
+
+        } // end withTransaction
+    } // savePicture
+
+    /**
+    * Import inventory pictures from an uploaded zip file or picture.
+    * @param request The http request to run getFile against.
+    * Get file should return a zip format file containing the inventory item pictures or a picture file.
+    */
+    def importInventoryItemPictures(request) {
+            def result = [:]
+
+            def kByteMultiplier = 1000
+            def mByteMultiplier = 1000 * kByteMultiplier
+            def fileMaxSize = 100 * mByteMultiplier
+
+            def fail = { Map m ->
+                result.error = [ code: m.code, args: m.args ]
+                return result
+            }
+
+            // Get file from request.
+            def multiPartFile = request.getFile('file')
+            def uploadedFileName = multiPartFile.originalFilename
+
+            if(!multiPartFile || multiPartFile.isEmpty())
+                return fail(code: "default.file.not.supplied")
+
+            if (multiPartFile.getSize() > fileMaxSize)
+                return fail(code: "default.file.over.max.size", args: [fileMaxSize/mByteMultiplier, "MB"])
+
+            // Check and create import dir.
+            def dir = new File(ConfigurationHolder.config.globalDirs.tempInventoryItemPicturesDirectory)
+
+            if(!dir.exists())
+                dir.mkdirs()
+
+            if(!dir.isDirectory()) {
+                return fail(code:'inventoryItemPictures.import.failure.no.directory')
+            }
+
+            // Write file to disk.
+            def diskFile = new File(dir.absolutePath + File.separator + uploadedFileName)
+            multiPartFile.transferTo(diskFile)
+
+            // File patterns
+            def zipFilePattern = ~/[^\s].*(\.(?i)(zip))$/
+            def pictureFilePattern = ~/[^\s].*(\.(?i)(jpg|png|gif|bmp))$/
+
+            // If file claims to be a zip file then try using ant to unzip.
+            if(diskFile.name.matches(zipFilePattern)) {
+                def ant = new AntBuilder()
+                try {
+                    ant.unzip(  src: diskFile.absolutePath,
+                                        dest: dir.absolutePath,
+                                        overwrite:"true" )
+                }
+                catch(e) {
+                    log.error e
+                    return fail(code:'inventoryItemPictures.import.failure.to.unzip')
+                }
+            }
+
+            // Recurse through dir building list of pictureFiles.
+            def pictureFiles = []
+            dir.eachFileMatch(pictureFilePattern) {
+                pictureFiles << it
+            }
+
+            dir.eachDirRecurse { subDir ->
+                subDir.eachFileMatch(pictureFilePattern) {
+                    pictureFiles << it
+                }
+            }
+
+            pictureFiles.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+
+            // Find inventoryItems by name of picture and call savePicture.
+            def inventoryItemInstance
+            def itemName
+            def savePictureResult
+            def pictureCount = 0
+            def picturesSavedCount = 0
+
+            // Turn off index mirroring.
+            createDataService.stopSearchableIndex()
+
+            for(pictureFile in pictureFiles) {
+                pictureCount++
+
+                if(pictureCount % 10 == 0) {
+                    cleanUpGorm()
+                }
+
+                itemName = WordUtils.capitalize(pictureFile.name[0..-5])
+                inventoryItemInstance = InventoryItem.findByName(itemName)
+                if(!inventoryItemInstance) {
+                    log.warn 'InventoryItem not found with name: ' + itemName
+                    continue
+                }
+                if(inventoryItemInstance.picture) {
+                    log.warn 'InventoryItem already has picture: ' + itemName
+                    continue
+                }
+                savePictureResult = savePicture(inventoryItemInstance, pictureFile)
+                if(savePictureResult.error)
+                    log.error savePictureResult.error
+                else {
+                    picturesSavedCount++
+                    log.info 'InventoryItem picture saved: ' + itemName
+                }
+            }
+
+            // Start mirroring again and rebuild index.
+            createDataService.startSearchableIndex()
+
+            log.info 'InventoryItem pictures saved: ' + picturesSavedCount
+            log.info 'InventoryItem pictures total: ' + pictureCount
+
+            // Cleanup.
+            dir.eachFile() {
+                if(it.isDirectory())
+                    it.deleteDir()
+                else
+                    it.delete()
+            }
+
+            // Success.
+            return result
+
+    } // importInventoryItemPictures
+
+    /**
+    * This cleans up the hibernate session and a grails map.
+    * For more info see: http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/
+    * The hibernate session flush is normal for hibernate.
+    * The map is apparently used by grails for domain object validation errors.
+    * A starting point for clean up is every 100 objects.
+    */
+    def cleanUpGorm() {
+        def session = sessionFactory.currentSession
+        session.flush()
+        session.clear()
+        propertyInstanceMap.get().clear()
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/InventoryMovementService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/InventoryMovementService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/InventoryMovementService.groovy	(revision 753)
@@ -0,0 +1,145 @@
+class InventoryMovementService {
+
+    boolean transactional = false
+
+    def authService
+    def authenticateService
+
+    def reverseMove(params) {
+        InventoryMovement.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryMovementInstance && m.field)
+                    result.inventoryMovementInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryMovement", params.id] ]
+                return result
+            }
+
+            result.inventoryMovementInstance = InventoryMovement.lock(params.id)
+
+             if(!result.inventoryMovementInstance)
+                fail(code:"default.not.found")
+
+            // Fetch to prevent lazy initialization error.
+            result.inventoryMovementInstance.inventoryItem.unitOfMeasure
+
+            // Used type must have a task that is not complete or in the trash
+            if(result.inventoryMovementInstance.inventoryMovementType.id == 1)  {
+
+                // Unlike move, if the task does not exist at all then deletion is still allowed.
+                if(result.inventoryMovementInstance.task?.trash)
+                    return fail(field:"task", code:"task.operationNotPermittedOnTaskInTrash")
+
+                if(result.inventoryMovementInstance.task?.taskStatus?.id == 3)
+                    return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
+
+                // Check for authorisation on recurring tasks.
+                if(result.inventoryMovementInstance.task?.taskRecurringSchedule) {
+                    if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager,ROLE_InventoryManager'))
+                        return fail(field:"task", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+                }
+
+            }
+
+            result.inventoryItemInstance = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id)
+            result.taskId = result.inventoryMovementInstance.task?.id
+
+            if(!result.inventoryItemInstance)
+                return fail(field:"inventoryItem", code:"inventoryMovement.inventoryItem.notFound")
+
+            // Reverse the movement of inventory.
+            if(!result.inventoryMovementInstance.inventoryMovementType.incrementsInventory) {
+                result.inventoryItemInstance.unitsInStock += result.inventoryMovementInstance.quantity
+            }
+            else {
+                if(result.inventoryItemInstance.unitsInStock >= result.inventoryMovementInstance.quantity) {
+                    result.inventoryItemInstance.unitsInStock -= result.inventoryMovementInstance.quantity
+                }
+                else {
+                    return fail(field:"quantity", code:"inventoryMovement.quantity.insufficientItemsInStock")
+                }
+            }
+
+            if(!result.inventoryItemInstance.save())
+                return fail(code: "default.delete.failure")
+
+            // Success..
+            result.inventoryMovementInstance.delete()
+            return result
+
+        } // end withTransaction
+    } //end reverseMove()
+
+    def move(params) {
+        InventoryMovement.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryMovementInstance && m.field)
+                    result.inventoryMovementInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryMovement", params.id] ]
+                return result
+            }
+
+            result.inventoryMovementInstance = new InventoryMovement(params)
+
+            result.inventoryMovementInstance.person = authService.currentUser
+
+            // Fetch to prevent lazy initialization error.
+            result.inventoryMovementInstance.inventoryItem.unitOfMeasure
+
+            // Used type must have a task that is not complete or in the trash
+            if(result.inventoryMovementInstance.inventoryMovementType.id == 1)  {
+
+                if(!result.inventoryMovementInstance.task)
+                    return fail(field:"task", code:"task.notFound")
+
+                if(result.inventoryMovementInstance.task.trash)
+                    return fail(field:"task", code:"task.operationNotPermittedOnTaskInTrash")
+
+                if(result.inventoryMovementInstance.task.taskStatus.id == 3)
+                    return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
+
+                // Check for authorisation on recurring tasks.
+                if(result.inventoryMovementInstance.task.taskRecurringSchedule) {
+                    if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager,ROLE_InventoryManager'))
+                        return fail(field:"task", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+                }
+            }
+
+            // Bail early if validation fails.
+            if(!result.inventoryMovementInstance.validate())
+                return fail(code:"default.create.failure")
+
+            def inventoryItem = InventoryItem.lock(result.inventoryMovementInstance.inventoryItem.id)
+            result.taskId = result.inventoryMovementInstance.task?.id
+
+            if(!inventoryItem)
+                return fail(field:"inventoryItem", code:"inventoryMovement.inventoryItem.notFound")
+
+            // Perform the movement of inventory.
+            if(result.inventoryMovementInstance.inventoryMovementType.incrementsInventory) {
+                inventoryItem.unitsInStock += result.inventoryMovementInstance.quantity
+            }
+            else {
+                if(inventoryItem.unitsInStock >= result.inventoryMovementInstance.quantity) {
+                    inventoryItem.unitsInStock -= result.inventoryMovementInstance.quantity
+                }
+                else {
+                    return fail(field:"quantity", code:"inventoryMovement.quantity.insufficientItemsInStock")
+                }
+            }
+
+            if(!inventoryItem.save() || !result.inventoryMovementInstance.save())
+                return fail(code:"default.create.failure")
+
+            // Success..
+            return result
+
+        } // end withTransaction
+    } // end move()
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/InventoryPurchaseService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/InventoryPurchaseService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/InventoryPurchaseService.groovy	(revision 753)
@@ -0,0 +1,478 @@
+class InventoryPurchaseService {
+
+    boolean transactional = false
+
+    def authService
+    def dateUtilService
+    def inventoryMovementService
+
+    /**
+    * Calulates the quantities for an inventoryItem and purchaseOrderNumber.
+    * @param order An inventory purchase that was the source of the order.
+    * @returns A result map containing the totalOrdered, totalReceived, totalRemaining, thisOrderRemaining,
+    *                 totalOrderedAmount, totalReceivedAmount, totalRemainingAmount, thisOrderRemainingAmount,
+    *                 totalPaymentApproved.
+    */
+    def calcQuantities(order) {
+
+        def result = [:]
+
+        result.totalOrdered = 0
+        result.totalOrderedAmount = 0
+        result.totalReceived = 0
+        result.totalReceivedAmount = 0
+        result.totalPaymentApproved = 0
+        InventoryItemPurchase.withCriteria {
+            eq("inventoryItem", order.inventoryItem)
+            eq("purchaseOrderNumber", order.purchaseOrderNumber)
+        }.each() {
+            if(it.inventoryItemPurchaseType.id == 1L) { // Orders.
+                result.totalOrdered += it.quantity
+                result.totalOrderedAmount += it.orderValueAmount
+            }
+            if(it.inventoryItemPurchaseType.id == 2L || it.inventoryItemPurchaseType.id == 3L) { // Received B/order and Complete.
+                result.totalReceived += it.quantity
+                result.totalReceivedAmount += it.orderValueAmount
+            }
+            if(it.inventoryItemPurchaseType.id == 4L) { // Approved.
+                result.totalPaymentApproved += it.orderValueAmount
+            }
+        }
+
+        result.totalRemaining
+        if(result.totalOrdered > result.totalReceived)
+            result.totalRemaining = result.totalOrdered - result.totalReceived
+        else
+            result.totalRemaining = 0
+
+        result.totalRemainingAmount
+        if(result.totalOrderedAmount > result.totalReceivedAmount)
+            result.totalRemainingAmount = result.totalOrderedAmount - result.totalReceivedAmount
+        else
+            result.totalRemainingAmount = 0
+
+        result.thisOrderRemaining
+        if(result.totalRemaining > order.quantity)
+            result.thisOrderRemaining = order.quantity
+        else
+            result.thisOrderRemaining = result.totalRemaining
+
+        result.thisOrderRemainingAmount
+        if(result.totalRemainingAmount > order.orderValueAmount)
+            result.thisOrderRemainingAmount = order.orderValueAmount
+        else
+            result.thisOrderRemainingAmount = result.totalRemainingAmount
+
+        return result
+    }
+
+    /**
+    * Get the original order for an inventoryItemPurchase and InventoryItem.
+    * @param inventoryItemPurchase An inventory puchase.
+    * @returns The order.
+    */
+    def getOriginalOrder(inventoryItemPurchase) {
+
+        def namedParams = [:]
+
+        namedParams.inventoryItem = inventoryItemPurchase.inventoryItem
+        namedParams.purchaseOrderNumber = inventoryItemPurchase.purchaseOrderNumber
+        namedParams.orderPlaced = InventoryItemPurchaseType.read(1)
+
+        def order = InventoryItemPurchase.find("from InventoryItemPurchase as p \
+                                                                                where( p.inventoryItem = :inventoryItem \
+                                                                                            and p.purchaseOrderNumber = :purchaseOrderNumber \
+                                                                                            and p.inventoryItemPurchaseType = :orderPlaced )",
+                                                                            namedParams)
+
+        return order
+    }
+
+    /**
+    * Get costCodes by person and the purchasingGroups they have been assigned.
+    * @param person A Person, defaults to currentUser.
+    * @returns A list of CostCodes.
+    */
+    def getCostCodesByPerson(person = authService.currentUser) {
+        if(person.purchasingGroups) {
+            CostCode.withCriteria {
+                    eq('isActive', true)
+                    or {
+                        person.purchasingGroups.each() { purchasingGroup ->
+                            eq('purchasingGroup', purchasingGroup)
+                        }
+                    }
+            }.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } // withCriteria
+        }
+        else
+            []
+    } // getCostCodesByPerson
+
+    /**
+    * Check if a person is in a purchasing group.
+    * @param person A PurchasingGroup to check for.
+    * @param person A Person, defaults to currentUser.
+    * @returns True if person is in group.
+    */
+    def isPersonInPurchasingGroup(purchasingGroup, person = authService.currentUser) {
+        for(pg in person.purchasingGroups) {
+            if(pg.id == purchasingGroup.id)
+                return true
+        }
+    } // isPersonInPurchasingGroup
+
+    def delete(params) {
+        InventoryItemPurchase.withTransaction { status ->
+            def result = [:]
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryItemPurchase && m.field)
+                    result.inventoryItemPurchase.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryItemPurchase", params.id] ]
+                return result
+            }
+
+            result.inventoryItemPurchaseInstance = InventoryItemPurchase.get(params.id)
+
+            if(!result.inventoryItemPurchaseInstance)
+                return fail(code:"default.not.found")
+
+            result.inventoryItemId = result.inventoryItemPurchaseInstance.inventoryItem.id
+            def purchaseTypeId = result.inventoryItemPurchaseInstance.inventoryItemPurchaseType.id
+
+            // Handle Invoice Payment Approved.
+            if(purchaseTypeId == 4) {
+                // Find and mark all orders as invoicePaymentApproved = false.
+                InventoryItemPurchase.withCriteria {
+                    eq("inventoryItem", result.inventoryItemPurchaseInstance.inventoryItem)
+                    eq("purchaseOrderNumber", result.inventoryItemPurchaseInstance.purchaseOrderNumber)
+                    inventoryItemPurchaseType {
+                            eq("id", 1L) // Order Placed.
+                    }
+                }.each() {
+                    it.invoicePaymentApproved = false
+                }
+                // Find and mark last orderReceived as invoicePaymentApproved = false.
+                InventoryItemPurchase.withCriteria {
+                    eq("inventoryItem", result.inventoryItemPurchaseInstance.inventoryItem)
+                    eq("purchaseOrderNumber", result.inventoryItemPurchaseInstance.purchaseOrderNumber)
+                    inventoryItemPurchaseType {
+                        or {
+                            eq("id", 2L) // Received B/order To Come
+                            eq("id", 3L) // Received Complete
+                        }
+                    }
+                }.last().invoicePaymentApproved = false
+            }
+
+            // Handle Received.
+            // Refuse to delete if payment approved.
+            // Find and reverse the matching movement.
+            // Find and mark all orders as receivedComplete = false.
+            if(purchaseTypeId == 2 || purchaseTypeId == 3) {
+
+                def paymentAlreadyApproved = InventoryItemPurchase.withCriteria {
+                    eq("inventoryItem", result.inventoryItemPurchaseInstance.inventoryItem)
+                    eq("purchaseOrderNumber", result.inventoryItemPurchaseInstance.purchaseOrderNumber)
+                    inventoryItemPurchaseType {
+                            eq("id", 4L) // Invoice Payment Approved.
+                    }
+                }
+
+                if(paymentAlreadyApproved)
+                    return fail(code:"inventoryItemPurchase.delete.failure.payment.approved")
+
+                def startOfDay = dateUtilService.getMidnight(result.inventoryItemPurchaseInstance.date)
+                def inventoryMovements = InventoryMovement.withCriteria {
+                    eq("inventoryItem", result.inventoryItemPurchaseInstance.inventoryItem )
+                    eq("quantity", result.inventoryItemPurchaseInstance.quantity)
+                    between("date", startOfDay, startOfDay+1)
+                    inventoryMovementType {
+                        eq("id", 3L) // purchaseReceived.
+                    }
+                    order('id', 'desc') // The newest one will be first.
+                }
+
+                def movementResult = inventoryMovementService.reverseMove(inventoryMovements[0])
+                if(movementResult.error)
+                    return fail(code:"inventoryMovement.quantity.insufficientItemsInStock")
+
+                InventoryItemPurchase.withCriteria {
+                    eq("inventoryItem", result.inventoryItemPurchaseInstance.inventoryItem)
+                    eq("purchaseOrderNumber", result.inventoryItemPurchaseInstance.purchaseOrderNumber)
+                    inventoryItemPurchaseType {
+                            eq("id", 1L) // Order Placed
+                    }
+                }.each() {
+                    it.receivedComplete = false
+                }
+            } // Handle Received.
+
+            // Handle Order Placed.
+            // Refuse to delete if we have received items.
+            // Deletion of received already requires payment approved to be deleted.
+            if(purchaseTypeId == 1) {
+                def calcQuantities = calcQuantities(result.inventoryItemPurchaseInstance)
+                if(calcQuantities.totalReceived > 0)
+                    return fail(code:"inventoryItemPurchase.delete.failure.received.exists")
+            }
+
+            // Success.
+            // By this stage everything should be handled and the delete call is allowed and expected to pass.
+            result.inventoryItemPurchaseInstance.delete()
+            return result
+
+        } // end withTransaction
+    }
+
+    def edit(params) {
+        def result = [:]
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: ["InventoryItemPurchase", params.id] ]
+            return result
+        }
+
+        result.inventoryItemPurchaseInstance = InventoryItemPurchase.get(params.id)
+
+        if(!result.inventoryItemPurchaseInstance)
+            return fail(code:"default.not.found")
+
+        // Success.
+        return result
+    }
+
+    def update(params) {
+        InventoryItemPurchase.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryItemPurchaseInstance && m.field)
+                    result.inventoryItemPurchaseInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryItemPurchase", params.id] ]
+                return result
+            }
+
+            result.inventoryItemPurchaseInstance = InventoryItemPurchase.get(params.id)
+
+            if(!result.inventoryItemPurchaseInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.inventoryItemPurchaseInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            def originalPaymentApprovedAmount = result.inventoryItemPurchaseInstance.orderValueAmount
+
+            result.inventoryItemPurchaseInstance.properties = params
+            result.inventoryItemPurchaseInstance.purchaseOrderNumber = result.inventoryItemPurchaseInstance.purchaseOrderNumber.trim()
+            result.inventoryItemPurchaseInstance.invoiceNumber = result.inventoryItemPurchaseInstance.invoiceNumber.trim()
+            result.inventoryItemPurchaseInstance.lastUpdatedBy = authService.currentUser
+
+            // Fetch to prevent lazy initialization error.
+            result.inventoryItemPurchaseInstance.inventoryItem.unitOfMeasure
+
+            //  If processing an Invoice Approved.
+            if(result.inventoryItemPurchaseInstance.inventoryItemPurchaseType.id == 4L) {
+                if(!result.inventoryItemPurchaseInstance.invoiceNumber)
+                    return fail(field:"invoiceNumber", code:"inventoryItemPurchase.invoiceNumber.required")
+            }
+
+            if(result.inventoryItemPurchaseInstance.hasErrors() || !result.inventoryItemPurchaseInstance.save())
+                return fail(code:"default.update.failure")
+
+            //  If processing an Invoice Approved.
+            if(result.inventoryItemPurchaseInstance.inventoryItemPurchaseType.id == 4L) {
+
+                def order = getOriginalOrder(result.inventoryItemPurchaseInstance)
+                if(!order)
+                    return fail(code:"default.not.found")
+
+                // Update orderValueAmount if receivedComplete.
+                if(order.receivedComplete) {
+
+                    def calcQuantities = calcQuantities(order)
+                    order.orderValueAmount = calcQuantities.totalPaymentApproved
+
+                    if(order.hasErrors() || !order.save())
+                        return fail(code:"default.create.failure")
+                }
+
+            }
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end update()
+
+    def save(params) {
+        InventoryItemPurchase.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryItemPurchase && m.field)
+                    result.inventoryItemPurchase.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryItemPurchase", params.id] ]
+                return result
+            }
+
+            result.inventoryItemPurchaseInstance = new InventoryItemPurchase(params)
+            result.inventoryItemPurchaseInstance.purchaseOrderNumber = result.inventoryItemPurchaseInstance.purchaseOrderNumber.trim()
+            result.inventoryItemPurchaseInstance.enteredBy = authService.currentUser
+            result.inventoryItemPurchaseInstance.inventoryItemPurchaseType = InventoryItemPurchaseType.read(1) // Order
+
+            // Fetch to prevent lazy initialization error.
+            result.inventoryItemPurchaseInstance.inventoryItem.unitOfMeasure
+
+            // Prevent ordering on obsolete or inactive inventoryItem.
+            def isObsolete = result.inventoryItemPurchaseInstance.inventoryItem?.isObsolete
+            def isActive = result.inventoryItemPurchaseInstance.inventoryItem?.isActive
+            if(isObsolete || !isActive)
+                return fail(code:"inventoryItemPurchase.operation.not.permitted.on.inactive.or.obsolete.item")
+
+            if(result.inventoryItemPurchaseInstance.hasErrors() || !result.inventoryItemPurchaseInstance.save())
+                return fail(code:"default.create.failure")
+
+            result.inventoryItemId = result.inventoryItemPurchaseInstance.inventoryItem.id
+
+            // success
+            return result
+
+        } // end withTransaction
+    } // save()
+
+    def receiveSave(params) {
+        InventoryItemPurchase.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryItemPurchase && m.field)
+                    result.inventoryItemPurchase.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryItemPurchase", params.id] ]
+                return result
+            }
+
+            def order = InventoryItemPurchase.get(params.orderId)
+            if(!order)
+                return fail(code:"default.not.found")
+            result.orderId = order.id
+
+            result.inventoryItemPurchaseInstance = new InventoryItemPurchase(params)
+            result.inventoryItemPurchaseInstance.enteredBy = authService.currentUser
+            result.inventoryItemPurchaseInstance.purchaseOrderNumber = order.purchaseOrderNumber
+            result.inventoryItemPurchaseInstance.costCode = order.costCode
+            result.inventoryItemPurchaseInstance.orderValueCurrency = order.orderValueCurrency
+
+            def calcQuantities = calcQuantities(order)
+            if(result.inventoryItemPurchaseInstance.quantity)
+                calcQuantities.totalReceived += result.inventoryItemPurchaseInstance.quantity
+            if(result.inventoryItemPurchaseInstance.orderValueAmount)
+                calcQuantities.totalReceivedAmount += result.inventoryItemPurchaseInstance.orderValueAmount
+
+            if(calcQuantities.totalReceived >= calcQuantities.totalOrdered) {
+                order.receivedComplete = true
+                result.inventoryItemPurchaseInstance.receivedComplete = true
+                result.inventoryItemPurchaseInstance.inventoryItemPurchaseType = InventoryItemPurchaseType.read(3) // Received Complete.
+            }
+            else {
+                order.receivedComplete = false
+                result.inventoryItemPurchaseInstance.inventoryItemPurchaseType = InventoryItemPurchaseType.read(2) // Received B/oder to Come.
+            }
+
+            // Fetch to prevent lazy initialization error.
+            result.inventoryItemPurchaseInstance.inventoryItem.unitOfMeasure
+            result.inventoryItemPurchaseInstance.inventoryItem.inventoryLocation
+
+            if(order.hasErrors() || !order.save())
+                return fail(code:"default.create.failure")
+
+            if(result.inventoryItemPurchaseInstance.hasErrors() || !result.inventoryItemPurchaseInstance.save())
+                return fail(code:"default.create.failure")
+
+            result.inventoryItemId = result.inventoryItemPurchaseInstance.inventoryItem.id
+
+            // Perform the inventory movement.
+            if(result.inventoryItemPurchaseInstance.quantity > 0) {
+                def p = [:]
+                p.inventoryItem = result.inventoryItemPurchaseInstance.inventoryItem
+                p.quantity = result.inventoryItemPurchaseInstance.quantity
+                p.inventoryMovementType = InventoryMovementType.read(3)
+                def movementResult = inventoryMovementService.move(p)
+                if(movementResult.error)
+                    return fail(code:"default.create.failure")
+            }
+
+            // success
+            return result
+
+        } // end withTransaction
+    } // receiveSave()
+
+    def approveInvoicePaymentSave(params) {
+        InventoryItemPurchase.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.inventoryItemPurchaseInstance && m.field)
+                    result.inventoryItemPurchaseInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["InventoryItemPurchase", params.id] ]
+                return result
+            }
+
+            def received = InventoryItemPurchase.get(params.receivedId)
+            if(!received)
+                return fail(code:"default.not.found")
+            result.receivedId = received.id
+
+            def order = getOriginalOrder(received)
+            if(!order)
+                return fail(code:"default.not.found")
+            result.orderId = order.id
+
+            result.inventoryItemPurchaseInstance = new InventoryItemPurchase(params)
+            result.inventoryItemPurchaseInstance.enteredBy = authService.currentUser
+            result.inventoryItemPurchaseInstance.purchaseOrderNumber = order.purchaseOrderNumber
+            result.inventoryItemPurchaseInstance.costCode = order.costCode
+            result.inventoryItemPurchaseInstance.orderValueCurrency = order.orderValueCurrency
+            result.inventoryItemPurchaseInstance.inventoryItemPurchaseType = InventoryItemPurchaseType.read(4) // Approve.
+
+            received.invoicePaymentApproved = true
+            result.inventoryItemPurchaseInstance.invoicePaymentApproved = true
+
+            // Update orderValueAmount and invoicePaymentApproved if processing a receivedComplete.
+            if(received.inventoryItemPurchaseType.id == 3L) {
+                order.invoicePaymentApproved = true
+                result.inventoryItemPurchaseInstance.receivedComplete = true
+                def calcQuantities = calcQuantities(order)
+                if(result.inventoryItemPurchaseInstance.orderValueAmount)
+                    calcQuantities.totalPaymentApproved += result.inventoryItemPurchaseInstance.orderValueAmount
+                order.orderValueAmount = calcQuantities.totalPaymentApproved
+            }
+
+            // Fetch to prevent lazy initialization error.
+            result.inventoryItemPurchaseInstance.inventoryItem.unitOfMeasure
+
+            if(!result.inventoryItemPurchaseInstance.invoiceNumber)
+                return fail(field:"invoiceNumber", code:"inventoryItemPurchase.invoiceNumber.required")
+
+            if(order.hasErrors() || !order.save())
+                return fail(code:"default.create.failure")
+
+            if(result.inventoryItemPurchaseInstance.hasErrors() || !result.inventoryItemPurchaseInstance.save())
+                return fail(code:"default.create.failure")
+
+            result.inventoryItemId = result.inventoryItemPurchaseInstance.inventoryItem.id
+
+            // Success..
+            return result
+
+        } // end withTransaction
+    } // approveInvoicePaymentSave()
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/InventoryReportService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/InventoryReportService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/InventoryReportService.groovy	(revision 753)
@@ -0,0 +1,365 @@
+
+import net.kromhouts.HqlBuilder
+
+/**
+* Service class that encapsulates the business logic for Inventory Reports.
+*/
+class InventoryReportService {
+
+    boolean transactional = false
+
+//     def authService
+//     def dateUtilService
+//     def messageSource
+
+    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
+
+    // Protect java heap memory.
+    // Most likely want to set paramsMax and inClauseMax to the same values.
+    def paramsMax = 250
+
+    // At least with Oracle and MSSQL db limits are 1000 (in list) and 2000 (nodes) respectively.
+    // But 255 has also been mentioned on the internet as a possible limit for some databases.
+    def inClauseMax = 250
+
+    /**
+    * Get the data for the inventory stock take overiew report.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getStockTakeOverview(params, locale) {
+        def result = [:]
+
+        result.summaryOfCalculationMethod = 'This report should be used in conjunction with the `Stock Take (By Location)` Report.'
+
+        def namedParams = [:]
+
+        result.query = "from InventoryLocation as inventoryLocation \
+                                        left join inventoryLocation.inventoryStore as inventoryStore \
+                                        where (inventoryLocation.isActive = true \
+                                                    ) \
+                                        order by inventoryStore.name, inventoryLocation.name"
+
+        result.query = "select new Map(inventoryLocation.name as location, inventoryStore.name as store) " + result.query
+        result.queryResult = InventoryLocation.executeQuery(result.query, namedParams)
+        result.inventoryLocationCount = result.queryResult.size()
+
+        result.inventoryLocationList = result.queryResult
+
+        // Success.
+        return result
+
+    } // getStockTakeOverview()
+
+    /**
+    * Get the data for the inventory stock take by location report.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getStockTakeByLocation(params, locale) {
+        def result = [:]
+
+        result.inventoryItemList = []
+        result.inventoryItemCount = 0
+        result.locationCount = 0
+        result.errorMessage = null
+        result.summaryOfCalculationMethod = 'This report should be used in conjunction with the `Stock Take (Overview)` Report.'
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: m.args ]
+            result.errorMessage = g.message(result.error)
+            result.locations = ''
+            return result
+        }
+
+        def paginateParams = [:]
+        paginateParams.max = Math.min(params?.max?.toInteger() ?: paramsMax, paramsMax)
+
+        def namedParams = [:]
+        namedParams.locationList = []
+
+        // Sanitise the user supplied locations string and convert to a list.
+        result.locations = params.locationString.trim()
+        if(result.locations.startsWith('e.g:'))
+            result.locations = result.locations.split(':')[-1].trim()
+        result.locations = result.locations.split(',')
+        result.locations = result.locations.collect {it.trim()}
+
+        // Fill namedParams.locationList.
+        result.locations.each() { location ->
+            if(namedParams.locationList.size() < paramsMax) {
+                // paramsMax+1 to ensure the too many locations check bellow is triggered.
+                namedParams.locationList += InventoryLocation.findAllByNameIlike(location, [max: paramsMax+1])
+            }
+            namedParams.locationList.unique()
+        }
+
+        // Return the actual locations as a string, along with a count.
+        result.locationCount = namedParams.locationList.size()
+        if(result.locationCount > 0) {
+            namedParams.locationList.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
+            result.locations = namedParams.locationList.toString()[1..-2]
+        }
+        else
+            result.locations = g.message(code: 'default.none.text')
+
+        // Exit if empty location list.
+        // Protects against HQL unexpected end of subtree exception with an empty list.
+        if(namedParams.locationList.isEmpty())
+            return fail(code:'report.error.no.locations.found')
+
+        // Exit if IN clause list too big.
+        if(namedParams.locationList.size() > inClauseMax)
+            return fail(code:'report.error.too.many.locations', args: [inClauseMax])
+
+        // Inventory List.
+        result.inventoryListQuery = "from InventoryItem as inventoryItem \
+                                                        left join inventoryItem.inventoryLocation as inventoryLocation \
+                                                        where (inventoryItem.isActive = true \
+                                                                    and  inventoryItem.inventoryLocation in (:locationList) \
+                                                                    ) "
+
+        result.inventoryCountQuery = "select count(distinct inventoryItem) " + result.inventoryListQuery
+        result.inventoryItemCount = InventoryItem.executeQuery(result.inventoryCountQuery, namedParams)[0]
+
+        // Exit if too many results.
+        if(result.inventoryItemCount > paramsMax) 
+            return fail(code:'report.error.too.many.results', args: [paramsMax])
+
+        result.inventoryListQuery = "select distinct inventoryItem " + result.inventoryListQuery
+        def inventoryList = InventoryItem.executeQuery(result.inventoryListQuery, namedParams, paginateParams)
+
+        // Reset namedParams for next query.
+        namedParams = [:]
+        namedParams.inventoryList = inventoryList
+
+        // Exit if empty inventory list.
+        // Protects against HQL unexpected end of subtree exception with an empty list.
+        if(namedParams.inventoryList.isEmpty())
+            return fail(code:'report.error.no.inventory.items.found')
+
+        // Exit if inventory list too big.
+        if(namedParams.inventoryList.size() > inClauseMax)
+            return fail(code:'report.error.too.many.inventory.items', args: [inClauseMax])
+
+        // Note: HQL docs advise 'not using fetch aliases in where clause (or any other clause)'.
+        // Access is via the parent object, however that does not work for the order by clause in this case.
+        result.query = "from InventoryItem as inventoryItem \
+                                        left join fetch inventoryItem.unitOfMeasure as unitOfMeasure \
+                                        left join fetch inventoryItem.inventoryLocation as inventoryLocation \
+                                        left join fetch inventoryLocation.inventoryStore as inventoryStore \
+                                        left join fetch inventoryItem.picture as picture \
+                                        left join fetch picture.images as Image \
+                                        where (inventoryItem in (:inventoryList) \
+                                                    ) \
+                                        order by inventoryStore.name, inventoryLocation.name"
+
+        // MSSQL will not do distinct here, for some reason it tries to compare the image data type!
+        result.query = "select inventoryItem " + result.query
+        result.inventoryItemList = InventoryItem.executeQuery(result.query, namedParams, paginateParams)
+
+        result.inventoryItemList.unique()
+
+        // Success.
+        return result
+
+    } // getStockTakeOverview()
+
+    /**
+    * Get the data for the inventory value with detail.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getInventoryValueDetailed(params, locale) {
+        def result = [:]
+
+        result.inventoryItemList = []
+        result.inventoryItemCount = 0
+        result.inventoryItemTotalValue = new BigDecimal(0)
+        result.currency = null
+        result.errorMessage = null
+        result.summaryOfCalculationMethod = "This report does not convert between different currency.\n"
+        result.summaryOfCalculationMethod += "Therefore all item's are checked to ensure that currency is the same."
+
+        result.site = Site.get(params.site.id.toLong())
+
+        result.inventoryTypes = []
+        if(params.inventoryTypes instanceof String)
+            result.inventoryTypes << InventoryType.get(params.inventoryTypes.toInteger())
+        else if(params.inventoryTypes)
+            result.inventoryTypes = params.inventoryTypes.collect { InventoryType.get(it.toInteger()) }
+        else
+            result.inventoryTypes = InventoryType.findAllByIsActive(true, [max:254, sort:'name'])
+
+        result.inventoryGroups = []
+        if(params.inventoryGroups instanceof String)
+            result.inventoryGroups << InventoryGroup.get(params.inventoryGroups.toInteger())
+        else if(params.inventoryGroups)
+            result.inventoryGroups = params.inventoryGroups.collect { InventoryGroup.get(it.toInteger()) }
+        else
+            result.inventoryGroups = InventoryGroup.findAllByIsActive(true, [max:254, sort:'name'])
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: m.args ]
+            result.errorMessage = g.message(result.error)
+            result.currency = null
+            result.inventoryItemTotalValue = new BigDecimal(0)
+            return result
+        }
+
+        def q = new HqlBuilder().query {
+            select 'distinct inventoryItem'
+            from 'InventoryItem as inventoryItem',
+                    'left join fetch inventoryItem.inventoryLocation as inventoryLocation',
+                    'left join fetch inventoryLocation.inventoryStore as inventoryStore',
+                    'left join fetch inventoryItem.unitOfMeasure as unitOfMeasure'
+            where 'inventoryItem.isActive = true'
+                namedParams.siteId = result.site.id
+                and 'inventoryStore.site.id = :siteId'
+                if(result.inventoryTypes) {
+                    namedParams.inventoryTypeIds = result.inventoryTypes.collect {it.id}
+                    and 'inventoryItem.inventoryType.id in(:inventoryTypeIds)'
+                }
+                if(result.inventoryGroups) {
+                    namedParams.inventoryGroupIds = result.inventoryGroups.collect {it.id}
+                    and 'inventoryItem.inventoryGroup.id in(:inventoryGroupIds)'
+                }
+            order 'by inventoryItem.name asc'
+        }
+
+        result.inventoryItemList = InventoryItem.executeQuery(q.query, q.namedParams)
+        result.inventoryItemCount = result.inventoryItemList.size()
+        result.currency = result.inventoryItemList[0]?.estimatedUnitPriceCurrency
+
+        for(inventoryItem in result.inventoryItemList) {
+            // Check all currency is the same.
+            if(result.currency != inventoryItem.estimatedUnitPriceCurrency) {
+                fail(code:'report.error.multiple.currency.found') // No return, populate errors but continue report.
+                break
+            }
+            if(inventoryItem.estimatedUnitPriceAmount && inventoryItem.unitsInStock) // Some items have null estimatedUnitPriceAmount.
+                result.inventoryItemTotalValue += inventoryItem.estimatedUnitPriceAmount * inventoryItem.unitsInStock
+        } // for
+
+        /// @todo: This protects against a bug in the report layout, remove when solved.
+        if(result.inventoryTypes.size() > 4)
+            result.inventoryTypes = [[name:'More than 4']]
+
+        if(result.inventoryGroups.size() > 4)
+            result.inventoryGroups =  [[name:'More than 4']]
+
+        // Success.
+        return result
+
+    } // getInventoryValueDetailed()
+
+    /**
+    * Get the data for the inventory overiew value.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getInventoryValueOverview(params, locale) {
+        def result = [:]
+
+        result.inventoryItemCount = 0
+        result.inventoryItemTotalValue = new BigDecimal(0)
+        result.currency = null
+        result.errorMessage = null
+        result.summaryOfCalculationMethod = "This report does not convert between different currency.\n"
+        result.summaryOfCalculationMethod += "Therefore all item's are checked to ensure that currency is the same."
+
+        result.site = Site.get(params.site.id.toLong())
+
+        result.inventoryTypes = []
+        if(params.inventoryTypes instanceof String)
+            result.inventoryTypes << InventoryType.get(params.inventoryTypes.toInteger())
+        else if(params.inventoryTypes)
+            result.inventoryTypes = params.inventoryTypes.collect { InventoryType.get(it.toInteger()) }
+        else
+            result.inventoryTypes = InventoryType.findAllByIsActive(true, [max:254, sort:'name'])
+
+        result.inventoryGroups = []
+        if(params.inventoryGroups instanceof String)
+            result.inventoryGroups << InventoryGroup.get(params.inventoryGroups.toInteger())
+        else if(params.inventoryGroups)
+            result.inventoryGroups = params.inventoryGroups.collect { InventoryGroup.get(it.toInteger()) }
+        else
+            result.inventoryGroups = InventoryGroup.findAllByIsActive(true, [max:254, sort:'name'])
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: m.args ]
+            result.errorMessage = g.message(result.error)
+            result.currency = null
+            //result.inventoryItemTotalValue = new BigDecimal(0)
+            return result
+        }
+
+        // Base query.
+        def q = new HqlBuilder().query {
+            select ''
+            from 'InventoryItem as inventoryItem',
+                    'left join inventoryItem.inventoryLocation as inventoryLocation',
+                    'left join inventoryLocation.inventoryStore as inventoryStore'
+            where 'inventoryItem.isActive = true'
+                namedParams.siteId = result.site.id
+                and 'inventoryStore.site.id = :siteId'
+                namedParams.groupIds = result.inventoryGroups.collect {it.id}
+                and 'inventoryItem.inventoryGroup.id in(:groupIds)'
+                namedParams.typeIds = result.inventoryTypes.collect {it.id}
+                and 'inventoryItem.inventoryType.id in(:typeIds)'
+        }
+        def baseWhereLogic = new ArrayList(q.whereClauseTerms)
+
+        // Count the inventoryItems.
+        q.select = 'count(distinct inventoryItem)'
+        result.inventoryItemCount = InventoryItem.executeQuery(q.query, q.namedParams)[0]
+
+        // Get the first currency found on this site.
+        q.paginateParams.max = 1
+        q.select = 'inventoryItem.estimatedUnitPriceCurrency'
+        result.currency = InventoryItem.executeQuery(q.query, q.namedParams, q.paginateParams)[0]
+
+        // Count the distinct currency found.
+        q.select = 'count(distinct inventoryItem.estimatedUnitPriceCurrency)'
+        def currencyCount = InventoryItem.executeQuery(q.query, q.namedParams)[0]
+
+        // Get total value.
+        q.select = 'sum (inventoryItem.estimatedUnitPriceAmount * inventoryItem.unitsInStock)'
+        result.inventoryItemTotalValue = InventoryItem.executeQuery(q.query, q.namedParams)[0]
+
+        // Get values for each group.
+        def tempGroups = []
+        result.inventoryGroups.each() { group ->
+            q.namedParams.groupIds = [group.id]
+            def groupValue = InventoryItem.executeQuery(q.query, q.namedParams)[0] ?: 0
+            tempGroups << [name: group.name, value: groupValue]
+        }
+        q.namedParams.groupIds = result.inventoryGroups.collect {it.id} // reset.
+        result.inventoryGroups = tempGroups
+
+        // Get values for each type.
+        def tempTypes = []
+        result.inventoryTypes.each() { type ->
+            q.namedParams.typeIds = [type.id]
+            def typeValue = InventoryItem.executeQuery(q.query, q.namedParams)[0] ?: 0
+            tempTypes << [name: type.name, value: typeValue]
+        }
+        result.inventoryTypes = tempTypes
+
+        /// @todo: This protects against a bug in the report layout, remove when solved.
+        if(result.inventoryTypes.size() > 4)
+            result.inventoryTypes = [[name:'More than 4', value: 0]]
+
+        if(result.inventoryGroups.size() > 4)
+            result.inventoryGroups =  [[name:'More than 4', value: 0]]
+
+        // Check all currency is the same.
+        if(currencyCount > 1)
+            fail(code:'report.error.multiple.currency.found') // No return, populate errors but continue report.
+
+        // Success.
+        return result
+
+    } // getInventoryValueOverview()
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/JsUtilService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/JsUtilService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/JsUtilService.groovy	(revision 753)
@@ -0,0 +1,91 @@
+/**
+* Provides some javascript utility methods.
+* For use with JsUtilTagLib.
+*/
+class JsUtilService {
+
+    boolean transactional = false
+
+    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
+
+    /**
+    * Toggle the visibility of an html element.
+    * @param id The html id of the element.
+    * @param type The type of html action the javascript will be applied to e.g 'onclick', defaults to 'href'.
+    * @returns A javascript string that can be assigned for example to an anchor href or onclick action.
+    */
+    def toggle(id, type="href") {
+        def s = 'toggleUtil(\"' + id + '\");'
+        if(type == "onclick")
+            s + ' return false;'
+        else
+            'javascript: ' + s
+    }
+
+    /**
+    * Toggle the visibility of an html element and update an image.
+    * @param toggleId The html id of the element to toggle.
+    * @param imageid The html id of the image to update.
+    * @param openImgUrl The url to apply as the image src when toggled element is visible.
+    * @param closedImgUrl The url to apply as the image src when toggled element is hidden.
+    * @param type The type of html action the javascript will be applied to e.g 'onclick', defaults to 'href'.
+    * @returns A javascript string that can be assigned for example to an anchor href or onclick action.
+    */
+    def toggleWithImg(toggleId, imageid, openImgUrl, closedImgUrl, type="href") {
+
+        def s = 'toggleWithImgUtil(\"' + toggleId +'\", \"' + imageid +'\", \"' + openImgUrl +'\", \"' + closedImgUrl +'\");'
+        if(type == "onclick")
+            s + ' return false;'
+        else
+            'javascript: ' + s
+
+    }
+
+    /**
+    * Show an html element by slowly increasing the visibility.
+    * @param id The html id of the element.
+    * @param type The type of html action the javascript will be applied to e.g 'onclick', defaults to 'href'.
+    * @returns A javascript string that can be assigned for example to an anchor href or onclick action.
+    */
+    def show(id) {
+        def s = 'showUtil(\"' + id + '\");'
+        if(type == "onclick")
+            s + ' return false;'
+        else
+            'javascript: ' + s
+    }
+
+    /**
+    * Hide an html element by slowly decreasing the visibility.
+    * @param id The html id of the element.
+    * @param type The type of html action the javascript will be applied to e.g 'onclick', defaults to 'href'.
+    * @returns A javascript string that can be assigned for example to an anchor href or onclick action.
+    */
+    def hide(id) {
+        def s = 'hideUtil(\"' + id + '\");'
+        if(type == "onclick")
+            s + ' return false;'
+        else
+            'javascript: ' + s
+    }
+
+    /**
+    * Toggle the visibility of an html element and update an image.
+    * @param toggleId The html id of the element to toggle.
+    * @param imageid The html id of the image to update.
+    * @param openImgUrl The url to apply as the image src when toggled element is visible.
+    * @param closedImgUrl The url to apply as the image src when toggled element is hidden.
+    * @param type The type of html action the javascript will be applied to e.g 'onclick', defaults to 'href'.
+    * @returns A javascript string that can be assigned for example to an anchor href or onclick action.
+    */
+    def toggleWithImgAndEffect(toggleId, imageid, openImgUrl, closedImgUrl, type="href") {
+
+        def s = 'toggleWithImgAndEffectUtil(\"' + toggleId +'\", \"' + imageid +'\", \"' + openImgUrl +'\", \"' + closedImgUrl +'\");'
+        if(type == "onclick")
+            s + ' return false;'
+        else
+            'javascript: ' + s
+
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/PersonCsvService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/PersonCsvService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/PersonCsvService.groovy	(revision 753)
@@ -0,0 +1,257 @@
+import grails.util.GrailsUtil
+import au.com.bytecode.opencsv.CSVWriter
+import au.com.bytecode.opencsv.CSVReader
+import org.apache.commons.lang.WordUtils
+
+/**
+ * Provides some csv import/export methods.
+ * Requires the opencsv jar to be available which is included in the grails-export plugin.
+ */
+class PersonCsvService {
+
+    boolean transactional = false
+
+    def authService
+
+    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
+
+    def sessionFactory
+    def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP
+
+    /**
+    * Import persons creating items as required.
+    */
+    def importPersons(request) {
+        Person.withTransaction { status ->
+            def result = [:]
+
+            def kByteMultiplier = 1000
+            def fileMaxSize = 800 * kByteMultiplier
+            def logFileLink = g.link(controller: "appCore", action: "appLog") {"log"}
+
+            def multiPartFile = request.getFile('file')
+
+            InputStreamReader sr = new InputStreamReader(multiPartFile.inputStream)
+            CSVReader reader = new CSVReader(sr)
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                reader.close()
+                result.error = [ code: m.code, args: m.args ]
+                return result
+            }
+
+            if(!multiPartFile || multiPartFile.isEmpty())
+                return fail(code: "default.file.not.supplied")
+
+            if (multiPartFile.getSize() > fileMaxSize)
+                return fail(code: "default.file.over.max.size", args: [fileMaxSize/kByteMultiplier, "kB"])
+
+            def line = []
+            def lineNumber = 0
+            def maxNumberOfColumns = 13
+            def personParams = [:]
+            def personProperties = ["loginName", "firstName", "lastName",
+                                                    "ROLE_Manager", "ROLE_AppUser",
+                                                    "ROLE_TaskManager", "ROLE_TaskUser",
+                                                    "ROLE_InventoryManager", "ROLE_InventoryUser",
+                                                    "ROLE_AssetManager", "ROLE_AssetUser",
+                                                    "ROLE_ProductionManager", "ROLE_ProductionUser"]
+
+            def personInstance
+            def loginNamesAndPasswords = [:]
+
+            def nextLine = {
+                    line = reader.readNext()
+                    lineNumber ++
+                    log.info "Processing line: " + lineNumber
+            }
+
+            // Get first line.
+            nextLine()
+
+            // Check for header line 1.
+            if(line != templateHeaderLine1) {
+                log.error "Failed to find header line 1. "
+                log.error "Required: " + templateHeaderLine1.toString()
+                log.error "Supplied: " + line.toString()
+                return fail(code: "default.file.no.header")
+            }
+
+            log.info "Header line found."
+
+            // Prepare the first body line.
+            nextLine()
+
+            // Primary loop.
+            while(line) {
+
+                if(line.size() > maxNumberOfColumns) {
+                    log.error "Too many columns on line: " + lineNumber
+                    return fail(code: "person.import.failure", args: [lineNumber, logFileLink])
+                }
+
+                // Ignore comment lines.
+                if(line.toString().toLowerCase().contains("comment")) {
+                    log.info "Comment line found."
+                    nextLine()
+                    continue
+                }
+
+                // Ignore example lines.
+                if(line.toString().toLowerCase().contains("example")) {
+                    log.info "Example line found."
+                    nextLine()
+                    continue
+                }
+
+                // Parse the line into the params map.
+                personParams = [:]
+                line.eachWithIndex { it, j ->
+                    personParams."${personProperties[j]}" = it.trim()
+                }
+
+                // Debug
+                log.debug " Supplied params: "
+                log.debug personParams
+
+                // Ignore blank lines.
+                if(personParams.loginName == '') {
+                    log.info "No login name found."
+                    nextLine()
+                    continue
+                }
+
+                // Login Name.
+                personParams.loginName = personParams.loginName.toLowerCase()
+
+                // First Name.
+                personParams.firstName = WordUtils.capitalizeFully(personParams.firstName)
+
+                // First Name.
+                personParams.lastName = WordUtils.capitalizeFully(personParams.lastName)
+
+                // Password.
+                personParams.pass = personParams.pass ?: authService.randomPassword
+
+                // Debug
+                log.debug "personParams: "
+                log.debug personParams
+
+                personInstance = Person.findByLoginName(personParams.loginName)
+
+                if(!personInstance) {
+                    log.info "Creating person with login name: " + personParams.loginName
+                    personInstance = new Person(loginName: personParams.loginName,
+                                                                                firstName: personParams.firstName,
+                                                                                lastName: personParams.lastName,
+                                                                                pass: personParams.pass,
+                                                                                password: authService.encodePassword(personParams.pass))
+
+                    // Save.
+                    if(personInstance.hasErrors() || !personInstance.save()) {
+                        log.error "Failed to create person on line: " + lineNumber
+                        log.debug personInstance.errors
+                        return fail(code: "person.import.failure", args: [lineNumber, logFileLink])
+                    }
+
+                    // Fill map with persons and passwords.
+                    loginNamesAndPasswords."${personParams.loginName}" = personParams.pass
+                }
+                else
+                    log.info "Person already exists with login name: " + personParams.loginName
+
+                // Add Authorities.
+                if('true'.equalsIgnoreCase(personParams.ROLE_Manager))
+                    personInstance.addToAuthorities(Authority.get(2))
+                if('true'.equalsIgnoreCase(personParams.ROLE_AppUser))
+                    personInstance.addToAuthorities(Authority.get(3))
+                if('true'.equalsIgnoreCase(personParams.ROLE_TaskManager))
+                    personInstance.addToAuthorities(Authority.get(4))
+                if('true'.equalsIgnoreCase(personParams.ROLE_TaskUser))
+                    personInstance.addToAuthorities(Authority.get(5))
+                if('true'.equalsIgnoreCase(personParams.ROLE_InventoryManager))
+                    personInstance.addToAuthorities(Authority.get(6))
+                if('true'.equalsIgnoreCase(personParams.ROLE_InventoryUser))
+                    personInstance.addToAuthorities(Authority.get(7))
+                if('true'.equalsIgnoreCase(personParams.ROLE_AssetManager))
+                    personInstance.addToAuthorities(Authority.get(8))
+                if('true'.equalsIgnoreCase(personParams.ROLE_AssetUser))
+                    personInstance.addToAuthorities(Authority.get(9))
+                if('true'.equalsIgnoreCase(personParams.ROLE_ProductionManager))
+                    personInstance.addToAuthorities(Authority.get(10))
+                if('true'.equalsIgnoreCase(personParams.ROLE_ProductionUser))
+                    personInstance.addToAuthorities(Authority.get(11))
+
+                if(lineNumber % 100 == 0)
+                    cleanUpGorm()
+
+                if(!result.error) nextLine()
+            } //while(line)
+
+            // Success.
+            log.info "End of file."
+            result.loginNamesAndPasswords = g.message(code: "person.import.success") + '\n'
+            result.loginNamesAndPasswords += "Login names and passwords: " + '\n'
+            result.loginNamesAndPasswords += '\n'
+            loginNamesAndPasswords.each() { result.loginNamesAndPasswords += (it.key + ' : ' + it.value + '\n') }
+            reader.close()
+            return result
+
+         } //end withTransaction
+    } // end importPersons()
+
+    /**
+    * Build a persons template csv file.
+    * This template can then be populated for import.
+    * @returns The template as a String in csv format.
+    */
+    def buildPersonsTemplate() {
+
+        StringWriter sw = new StringWriter()
+        CSVWriter writer = new CSVWriter(sw)
+
+        writeTemplateLines(writer)
+
+        writer.close()
+        return sw.toString()
+    }
+
+    private writeTemplateLines(writer) {
+        writer.writeNext(templateHeaderLine1 as String[])
+        writer.writeNext()
+        writer.writeNext("Comment: The header line is required.")
+        writer.writeNext("Comment: Required columns are marked with a (*) in the header line.")
+        writer.writeNext("Comment: Lists of items in a column must be separated by a semicolon (;), not a comma.")
+        writer.writeNext("Comment: Role columns must be 'true' or 'false'.")
+        writer.writeNext("Comment: Identical and existing names will be considered as the same item.")
+        writer.writeNext("Comment: Lines containing 'comment' will be ignored.")
+        writer.writeNext("Comment: Lines containing 'example' will be ignored.")
+        writer.writeNext("Comment: This file must be saved as a CSV file before import.")
+        writer.writeNext()
+    }
+
+    private getTemplateHeaderLine1() {
+            ["Login Name*", "First Name*", "Last Name*",
+            "Role: Business Manager*", "Role: Application User*",
+            "Role: Task Manager*", "Role: Task User*",
+            "Role: Inventory Manager*", "Role: Inventory User*",
+            "Role: Asset Manager*", "Role: Asset User*",
+            "Role: Production Manager*", "Role: Production User*"]
+    }
+
+    /**
+    * This cleans up the hibernate session and a grails map.
+    * For more info see: http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/
+    * The hibernate session flush is normal for hibernate.
+    * The map is apparently used by grails for domain object validation errors.
+    * A starting point for clean up is every 100 objects.
+    */
+    def cleanUpGorm() {
+        def session = sessionFactory.currentSession
+        session.flush()
+        session.clear()
+        propertyInstanceMap.get().clear()
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/SectionService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/SectionService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/SectionService.groovy	(revision 753)
@@ -0,0 +1,55 @@
+class SectionService {
+
+    boolean transactional = false
+
+    def assetSubItemService
+    def assetService
+
+    def delete(params) {
+        Section.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.sectionInstance && m.field)
+                    result.sectionInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Section", params.id] ]
+                return result
+            }
+
+            result.sectionInstance = Section.get(params.id)
+
+            if(!result.sectionInstance)
+                return fail(code:"default.not.found")
+
+            if(result.sectionInstance.maintenanceActions)
+                return fail(code:"maintenanceActions.still.associated")
+
+            // Delete assets which in turn delete orphan assetSubItems.
+            def assets = new ArrayList(result.sectionInstance.assets) // avoid ConcurrentModificationException.
+            def r
+            for(asset in assets) {
+                result.sectionInstance.removeFromAssets(asset)
+                r = assetService.delete(id: asset.id)
+                if(r.error) {
+                    log.debug r.error
+                    fail(code:"section.asset.delete.failure")
+                    break
+                }
+            }
+
+            if(result.error)
+                return result
+
+            try {
+                result.sectionInstance.delete(flush:true)
+                return result //Success.
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                return fail(code:"default.delete.failure")
+            }
+
+        } // end withTransaction
+    } // end delete()
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/SiteService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/SiteService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/SiteService.groovy	(revision 753)
@@ -0,0 +1,54 @@
+class SiteService {
+
+    boolean transactional = false
+
+    def sectionService
+
+    def delete(params) {
+        Site.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.siteInstance && m.field)
+                    result.siteInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Site", params.id] ]
+                return result
+            }
+
+            result.siteInstance = Site.get(params.id)
+
+            if(!result.siteInstance)
+                return fail(code:"default.not.found")
+
+            if(result.siteInstance.inventoryStores)
+                return fail(code:"inventoryStores.still.associated")
+
+            // Delete sections which in turn deletes assets etc.
+            def sections = new ArrayList(result.siteInstance.sections) // avoid ConcurrentModificationException.
+            def r
+            for(section in sections) {
+                result.siteInstance.removeFromSections(section)
+                r = sectionService.delete(id: section.id)
+                if(r.error) {
+                    log.debug r.error
+                    fail(code:"site.section.delete.failure")
+                    break
+                }
+            }
+
+            if(result.error)
+                return result
+
+            try {
+                result.siteInstance.delete(flush:true)
+                return result //Success.
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                return fail(code:"default.delete.failure")
+            }
+
+        } // end withTransaction
+    } // end delete()
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/TaskRecurringScheduleService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/TaskRecurringScheduleService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/TaskRecurringScheduleService.groovy	(revision 753)
@@ -0,0 +1,195 @@
+class TaskRecurringScheduleService {
+
+    boolean transactional = false
+
+    // Can hold state since the service is a singleton.
+    boolean baseDataWarnLogged = false
+
+    def taskService
+    def dateUtilService
+    def appConfigService
+
+    /**
+    * Generate all enabled recurring tasks.
+    */
+    def generateAll() {
+
+        // Prevent errors if base data has not yet been created.
+        if(!appConfigService.exists("baseDataCreated")) {
+            if(!baseDataWarnLogged) {
+                log.warn "Base data has not been created, can't generate all."
+                baseDataWarnLogged = true
+            }
+            return
+        }
+
+        def p = [:]
+        def targetCompletionDate
+        def nextTargetCompletionDate
+        def tomorrow = dateUtilService.tomorrow
+
+        def taskRecurringScheduleList = TaskRecurringSchedule.findAllByEnabled(true)
+
+        // Stop generation if max reached.
+        def maxSubTasksReached = {
+            if( (it.maxSubTasks > 0) && (it.subTasksGenerated >= it.maxSubTasks) ) {
+                it.enabled = false
+                return true
+            }
+            return false
+        }
+
+        // Stop generation by targetCompletionDate.
+        def targetCompletionDateReached = {
+            if( it.useTargetCompletionDate) {
+                targetCompletionDate = dateUtilService.getMidnight(it.task.targetCompletionDate)
+                nextTargetCompletionDate = dateUtilService.getMidnight(it.nextTargetCompletionDate)
+                if(nextTargetCompletionDate > targetCompletionDate) {
+                    it.enabled = false
+                    return true
+                }
+            }
+            return false
+        }
+
+        // Main loop.
+        for(it in taskRecurringScheduleList) {
+
+            if(maxSubTasksReached(it))
+                continue
+
+            if(targetCompletionDateReached(it))
+                continue
+
+            if (dateUtilService.tomorrow > it.nextGenerationDate) {
+                p = [:]
+
+                // Build the subTask params.
+                p.targetStartDate = it.nextTargetStartDate
+                p.targetCompletionDate = it.nextTargetCompletionDate
+                if(it.task.taskProcedure) p.taskProcedure = it.task.taskProcedure
+                if(it.task.assignedGroups) p.assignedGroups = new ArrayList(it.task.assignedGroups)
+                if(it.task.assignedPersons) p.assignedPersons = new ArrayList(it.task.assignedPersons)
+
+                def result = taskService.createSubTask(it.task, p)
+                if( !result.error ) {
+                    it.lastGeneratedSubTask = result.taskInstance
+                    it.subTasksGenerated++
+                    it.setNextTargetStartDate()
+                    it.setNextGenerationDate()
+                    it.setNextTargetCompletionDate()
+                }
+                else {
+                    log.error "Sub task generation for recurring schedule ${it.id} failed."
+                    log.error result.taskInstance.errors
+                }
+            }
+
+            // Run the completion reached checks for a second time so
+            // that this recurring schedule does not run again if
+            // there are no more subTasks to be generated.
+            if(maxSubTasksReached(it))
+                continue
+
+            if(targetCompletionDateReached(it))
+                continue
+
+        } // for()
+    } // generateAll()
+
+    /**
+    * Creates a new recurring schedule for a task with the given params.
+    * @param params The params to use when creating the new recurring schedule.
+    * @returns A map containing result.error=true (if any error) and result.taskRecurringScheduleInstance and result.taskId.
+    */
+    def create(params) {
+        TaskRecurringSchedule.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Object[] args ->
+                status.setRollbackOnly()
+                if(args.size() == 2) result.taskRecurringScheduleInstance.errors.rejectValue(args[0], args[1])
+                result.error = true
+                return result
+            }
+
+            result.taskRecurringScheduleInstance = new TaskRecurringSchedule(params)
+            result.taskId = result.taskRecurringScheduleInstance.task.id
+
+            if(!result.taskRecurringScheduleInstance.validate())
+                return fail()
+
+            def taskInstance = Task.lock(result.taskId)
+
+            if(!taskInstance)
+                return fail('task', "task.notFound")
+
+            if(taskInstance.taskRecurringSchedule)
+                return fail('task', "tast.taskRecurringSchedule.alreadyExists")
+
+            if(taskInstance.taskStatus.id == 3)
+                return fail('task', "task.operationNotPermittedOnCompleteTask")
+
+            if(taskInstance.trash)
+                return fail('task', "task.operationNotPermittedOnTaskInTrash")
+
+            if(result.taskRecurringScheduleInstance.nextTargetStartDate < dateUtilService.today)
+                return fail("nextTargetStartDate", "taskRecurringSchedule.nextTargetStartDate.mayNotBePast")
+
+            taskInstance.taskRecurringSchedule = result.taskRecurringScheduleInstance
+
+            if(!result.taskRecurringScheduleInstance.save() || !taskInstance.save())
+                return fail()
+
+             // If we get here all went well.
+            return result
+
+        } //end withTransaction
+    } // end create()
+
+    /**
+    * Updates an existing recurring schedule.
+    * @param params The params to update for recurring schedule with id of params.id.
+    * @returns A map containing result.error=true (if any error) and result.taskRecurringScheduleInstance (if available).
+    */
+    def update(params) {
+        TaskRecurringSchedule.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Object[] args ->
+                status.setRollbackOnly()
+                if(args.size() == 2) result.taskRecurringScheduleInstance.errors.rejectValue(args[0], args[1])
+                result.error = true
+                return result
+            }
+
+            result.taskRecurringScheduleInstance = TaskRecurringSchedule.get(params.id)
+
+            if(!result.taskRecurringScheduleInstance)
+                return fail('id', "taskRecurringSchedule.notFound")
+
+            // Optimistic locking check.
+            if(params.version) {
+                def version = params.version.toLong()
+                if(result.taskRecurringScheduleInstance.version > version)
+                    return fail("version", "default.optimistic.locking.failure")
+            }
+
+            result.taskRecurringScheduleInstance.properties = params
+
+            if(result.taskRecurringScheduleInstance.nextTargetStartDate < dateUtilService.today)
+                return fail("nextTargetStartDate", "taskRecurringSchedule.nextTargetStartDate.mayNotBePast")
+
+            result.taskRecurringScheduleInstance.setNextGenerationDate()
+            result.taskRecurringScheduleInstance.setNextTargetCompletionDate()
+
+            if(result.taskRecurringScheduleInstance.hasErrors() || !result.taskRecurringScheduleInstance.save())
+                return fail()
+
+            // If we get here all went well.
+            return result
+
+        } //end withTransaction
+    }  // end update()
+
+} // end of class
Index: branches/features/taskProcedureRework/grails-app/services/TaskReportService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/TaskReportService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/TaskReportService.groovy	(revision 753)
@@ -0,0 +1,337 @@
+import org.gnumims.RichUiCalendarItem
+
+/**
+* Service class that encapsulates the business logic for Task Reports.
+*/
+class TaskReportService {
+
+    boolean transactional = false
+
+    def authService
+    def dateUtilService
+//     def messageSource
+
+    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
+
+    def paramsMax = 100000
+
+    /**
+    * Selects and returns the reactive ratio.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getReactiveRatio(params, locale) {
+        def result = [:]
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: [] ]
+            return result
+        }
+
+        def namedParams = [:]
+        namedParams.startDate = params.startDate ?: dateUtilService.today
+        namedParams.endDate = params.endDate ?: dateUtilService.today
+
+        // Auto swap date range.
+        if(namedParams.startDate > namedParams.endDate) {
+            def tempStartDate = namedParams.startDate
+            namedParams.startDate = namedParams.endDate
+            namedParams.endDate = tempStartDate
+        }
+
+        result.startDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: namedParams.startDate)
+        result.endDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: namedParams.endDate)
+
+        namedParams.endDate++ // Start of next day required.
+
+        namedParams.immediateCallout = TaskType.read(1)
+        namedParams.unscheduledBreakin = TaskType.read(2)
+        namedParams.preventativeMaintenance = TaskType.read(4)
+        namedParams.notStarted = TaskStatus.read(1)
+
+        result.taskQuery = "from Task as task \
+                                            where (task.trash = false \
+                                                        and task.taskStatus != :notStarted \
+                                                        and task.targetStartDate < :endDate \
+                                                        and task.targetStartDate >= :startDate \
+                                                        and ( \
+                                                            task.taskType = :immediateCallout \
+                                                            or task.taskType = :unscheduledBreakin \
+                                                            or task.taskType = :preventativeMaintenance \
+                                                        ) \
+                                            )"
+
+        result.taskQuery = "select distinct task " + result.taskQuery
+        result.taskList = Task.executeQuery(result.taskQuery, namedParams)
+        result.taskCount = result.taskList.size()
+
+        // Assets on Tasks Count.
+        result.totalAssetsOnTasksCount = 0
+        result.immediateCalloutCount = 0
+        result.unscheduledBreakinCount = 0
+        result.preventativeMaintenanceCount = 0
+
+        // Summary Of Calculations.
+        result.summaryOfCalculationMethod = 'HQL query: \n\n'
+        def tempStringArray = result.taskQuery.split('    ')
+        tempStringArray.each() {
+            if(it != '') result.summaryOfCalculationMethod += it +'\n'
+        }
+        result.summaryOfCalculationMethod += '\n'+'Calculations: '+'\n\n'
+
+        result.summaryOfCalculationMethod += 'totalAssetsOnTasksCount = A count of unique assets on each task. \n'
+        result.taskList.each() { task ->
+            if(task.primaryAsset) {
+                result.totalAssetsOnTasksCount++
+                if(task.taskType == namedParams.immediateCallout) result.immediateCalloutCount++
+                if(task.taskType == namedParams.unscheduledBreakin) result.unscheduledBreakinCount++
+                if(task.taskType == namedParams.preventativeMaintenance) result.preventativeMaintenanceCount++
+            }
+            task.associatedAssets.each() { associatedAsset ->
+                if(associatedAsset.id != task.primaryAsset?.id) {
+                    result.totalAssetsOnTasksCount++
+                    if(task.taskType == namedParams.immediateCallout) result.immediateCalloutCount++
+                    if(task.taskType == namedParams.unscheduledBreakin) result.unscheduledBreakinCount++
+                    if(task.taskType == namedParams.preventativeMaintenance) result.preventativeMaintenanceCount++
+                }
+            }
+        } // each() task
+
+        // Percentage of counts.
+        result.immediateCalloutPercentage = 0
+        result.totalPreventativePercentage = 0
+
+        result.summaryOfCalculationMethod += 'totalPreventativeCount = unscheduledBreakinCount + preventativeMaintenanceCount\n'
+        result.totalPreventativeCount = result.unscheduledBreakinCount + result.preventativeMaintenanceCount
+        try {
+            result.summaryOfCalculationMethod += 'immediateCalloutPercentage = (immediateCalloutCount / totalAssetsOnTasksCount)*100 \n'
+            result.summaryOfCalculationMethod += 'totalPreventativePercentage = (totalPreventativeCount / totalAssetsOnTasksCount)*100 \n'
+            result.immediateCalloutPercentage = (result.immediateCalloutCount / result.totalAssetsOnTasksCount)*100
+            result.totalPreventativePercentage = (result.totalPreventativeCount / result.totalAssetsOnTasksCount)*100
+        }
+        catch(ArithmeticException e) {
+            log.info "Could not calculate: Assets on Tasks Percentages: "+e
+        }
+
+        // Work Done.
+        result.immediateCalloutWorkDone = [total:0, hours:0, minutes:0, percentage: new BigDecimal(0)]
+        result.unscheduledBreakinWorkDone = [total:0, hours:0, minutes:0]
+        result.preventativeMaintenanceWorkDone = [total:0, hours:0, minutes:0]
+        result.totalPreventativeWorkDone = [total:0, hours:0, minutes:0, percentage: new BigDecimal(0)]
+        result.totalWorkDone = [total:0, hours:0, minutes:0]
+
+        result.taskList.each() { task ->
+            task.entries.each() { entry ->
+                // Has assets assigned and is Work Done.
+                if( (task.primaryAsset || task.associatedAssets) && entry.entryType.id == 3L ) {
+                        if(task.taskType == namedParams.immediateCallout)
+                            result.immediateCalloutWorkDone.total += (entry.durationHour*60) + entry.durationMinute
+                        if(task.taskType == namedParams.unscheduledBreakin)
+                            result.unscheduledBreakinWorkDone.total += (entry.durationHour*60) + entry.durationMinute
+                        if(task.taskType == namedParams.preventativeMaintenance)
+                            result.preventativeMaintenanceWorkDone.total += (entry.durationHour*60) + entry.durationMinute
+                }
+            } // each() entry
+        } // each() task
+
+        // Work Done hours and minutes.
+        result.immediateCalloutWorkDone.hours = (result.immediateCalloutWorkDone.total / 60).toInteger()
+        result.immediateCalloutWorkDone.minutes = result.immediateCalloutWorkDone.total % 60
+
+        result.unscheduledBreakinWorkDone.hours = (result.unscheduledBreakinWorkDone.total / 60).toInteger()
+        result.unscheduledBreakinWorkDone.minutes = result.unscheduledBreakinWorkDone.total % 60
+
+        result.preventativeMaintenanceWorkDone.hours = (result.preventativeMaintenanceWorkDone.total / 60).toInteger()
+        result.preventativeMaintenanceWorkDone.minutes = result.preventativeMaintenanceWorkDone.total % 60
+
+        // Work Done Totals.
+        result.totalPreventativeWorkDone.total = result.unscheduledBreakinWorkDone.total + result.preventativeMaintenanceWorkDone.total
+        result.totalPreventativeWorkDone.hours = (result.totalPreventativeWorkDone.total / 60).toInteger()
+        result.totalPreventativeWorkDone.minutes = result.totalPreventativeWorkDone.total % 60
+
+        result.totalWorkDone.total = result.immediateCalloutWorkDone.total + result.totalPreventativeWorkDone.total
+        result.totalWorkDone.hours = (result.totalWorkDone.total / 60).toInteger()
+        result.totalWorkDone.minutes = result.totalWorkDone.total % 60
+
+        // Work Done Percentages.
+        try {
+            result.immediateCalloutWorkDone.percentage = (BigDecimal)(result.immediateCalloutWorkDone.total / result.totalWorkDone.total)*100
+            result.totalPreventativeWorkDone.percentage = (BigDecimal)(result.totalPreventativeWorkDone.total / result.totalWorkDone.total)*100
+        }
+        catch(ArithmeticException e) {
+            log.info "Could not calculate: Work Done Percentages: "+e
+        }
+
+        // Success.
+        return result
+
+    } // getReactiveRatio
+
+    /**
+    * Selects and returns Immediate Callouts, grouped by Asset.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getImmediateCallouts(params, locale) {
+        def result = [:]
+
+        def fail = { Map m ->
+            result.error = [ code: m.code, args: [] ]
+            return result
+        }
+
+        def namedParams = [:]
+        namedParams.startDate = params.startDate ?: dateUtilService.today
+        namedParams.endDate = params.endDate ?: dateUtilService.today
+
+        // Auto swap date range.
+        if(namedParams.startDate > namedParams.endDate) {
+            def tempStartDate = namedParams.startDate
+            namedParams.startDate = namedParams.endDate
+            namedParams.endDate = tempStartDate
+        }
+
+        result.startDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: namedParams.startDate)
+        result.endDateString = g.formatDate(format: "EEE, dd-MMM-yyyy", date: namedParams.endDate)
+
+        namedParams.endDate++ // Start of next day required.
+
+        namedParams.immediateCallout = TaskType.read(1)
+
+        result.taskQuery = "from Task as task \
+                                            where (task.trash = false \
+                                                        and task.targetStartDate < :endDate \
+                                                        and task.targetStartDate >= :startDate \
+                                                        and task.taskType = :immediateCallout \
+                                                        ) \
+                                            )"
+
+        result.taskQuery = "select distinct task " + result.taskQuery
+        result.taskQueryList = Task.executeQuery(result.taskQuery, namedParams)
+        result.taskCount = result.taskQueryList.size()
+
+        // Assets on Tasks Count.
+        result.totalAssetsOnTasksCount = 0
+        result.totalDownTime = [total: 0, hours: 0, minutes:0]
+        result.assetList = []
+
+        // Task Details
+        result.taskList = []
+
+        // Add or update lists.
+        def addToLists = { asset, task ->
+
+            def downTime = 0
+            def faultEntries = Entry.findAllByTaskAndEntryType(task, EntryType.read(1))
+            def causeEntries = Entry.findAllByTaskAndEntryType(task, EntryType.read(2))
+            def workDoneEntries = Entry.findAllByTaskAndEntryType(task, EntryType.read(3))
+            def taskDetails = 'Task #'+task.id+' - '+task.description+'\n'
+            faultEntries.each(){
+                taskDetails += '    Faults: '+it.comment+' - '+it.enteredBy+', '+g.formatDate(format: "EEE, dd-MMM-yyyy", date: it.dateDone)+'.\n'
+            }
+            causeEntries.each(){
+                taskDetails += '    Causes: '+it.comment+' - '+it.enteredBy+', '+g.formatDate(format: "EEE, dd-MMM-yyyy", date: it.dateDone)+'.\n'
+            }
+            workDoneEntries.each(){
+                taskDetails += '    Work Done: '+it.comment+' - '+it.enteredBy+', '+g.formatDate(format: "EEE, dd-MMM-yyyy", date: it.dateDone)+'.\n'
+            }
+
+            faultEntries.each() { downTime += (it.durationHour*60 + it.durationMinute) }
+            result.totalDownTime.total += downTime
+
+            def assetDetails = result.assetList.find { it.id == asset.id }
+            if(assetDetails) {
+                assetDetails.immediateCalloutCount++
+                assetDetails.downTime += downTime
+                assetDetails.tasks += taskDetails
+            }
+            else {
+                assetDetails = [id: asset.id,
+                                            name: asset.name,
+                                            immediateCalloutCount: 1,
+                                            downTime: downTime,
+                                            tasks: taskDetails]
+
+                result.assetList << assetDetails
+            }
+        } // addAToLists
+
+        // Summary Of Calculations.
+        result.summaryOfCalculationMethod = 'HQL query: \n\n'
+        def tempStringArray = result.taskQuery.split('    ')
+        tempStringArray.each() {
+            if(it != '') result.summaryOfCalculationMethod += it +'\n'
+        }
+        result.summaryOfCalculationMethod += '\n'+'Calculations: '+'\n\n'
+
+        result.summaryOfCalculationMethod += 'totalAssetsOnTasksCount = A count of unique assets on each task. \n'
+        result.taskQueryList.each() { task ->
+            if(task.primaryAsset) {
+                result.totalAssetsOnTasksCount++
+                addToLists(task.primaryAsset, task)
+            }
+            task.associatedAssets.each() { associatedAsset ->
+                if(associatedAsset.id != task.primaryAsset?.id) {
+                    result.totalAssetsOnTasksCount++
+                    addToLists(associatedAsset, task)
+                }
+            }
+
+        } // each() task
+
+        // Sort assetList by callout count.
+        result.assetList.sort {a, b -> b.immediateCalloutCount.compareTo(a.immediateCalloutCount)}
+
+        // Calculate hours and minutes.
+        result.totalDownTime.hours = (result.totalDownTime.total / 60).toInteger()
+        result.totalDownTime.minutes = result.totalDownTime.total % 60
+
+        // Success.
+        return result
+
+    } // getImmediateCallouts()
+
+    /**
+    * Builds and returns a list of RichUiCalendarItem's.
+    * @param params The request params, may contain params to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getWorkLoadSummary(params, locale) {
+
+        def result = [:]
+        result.displayList = []
+
+        def listItem
+
+        def dayMap = [:]
+        def assignedGroupMap = [:]
+
+        params.taskInstanceList.each { task ->
+            def dayKey = task.targetStartDate /// @todo: make this key more stable.
+            def assignedTime = 0
+
+            task.assignedGroups.each{ assignedGroup ->
+                assignedTime = assignedGroup.estimatedHour*60 + assignedGroup.estimatedMinute
+            }
+
+            if(dayMap.containsKey(dayKey)) {
+                if(task.description) {
+                    dayMap[dayKey] = dayMap[dayKey] + assignedTime
+                }
+            }
+            else {
+                dayMap[(dayKey)] = assignedTime
+            }
+        }
+
+        dayMap.each { k, v ->
+                listItem = new RichUiCalendarItem(date:k, text:('assignedTime: '+v.toString()))
+                result.displayList << listItem
+        }
+
+        // Success.
+        return result
+
+    } // getWorkLoadSummary()
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/TaskSearchService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/TaskSearchService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/TaskSearchService.groovy	(revision 753)
@@ -0,0 +1,538 @@
+import net.kromhouts.HqlBuilder
+import grails.orm.PagedResultList
+import org.hibernate.FetchMode as FM
+
+/**
+* Service class that encapsulates the business logic for Task searches.
+*/
+class TaskSearchService {
+
+    boolean transactional = false
+
+    def authService
+    def dateUtilService
+    def messageSource
+
+    def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
+
+    def paramsMax = 100000
+
+    // Be sure to update taskQuickSearchPane.js if quickSearchSelection is changed.
+    def getQuickSearchSelection() {
+        [ 'allTasks': g.message(code: 'task.search.text.all.tasks'),
+        'personsImmediateCallouts': g.message(code: 'task.search.text.persons.immediate.callouts'),
+        'personsTasks': g.message(code: 'task.search.text.persons.tasks')
+        ]
+    }
+
+    /**
+    * Selects and returns the correct search results based on the supplied quickSearch.
+    * @param params The request params, may contain params.quickSearch string to specify the search.
+    * @param locale The locale to use when generating result.message.
+    */
+    def getQuickSearch(params = [:], locale) {
+        def result = [:]
+        result.quickSearch = params.quickSearch ?: "personsTasks"
+        if(params.person)
+            result.person = Person.get(params.person.id.toLong())
+        else
+            result.person = authService.currentUser
+        result.startDate = params.startDate ?: dateUtilService.today
+        result.endDate = params.endDate ?: dateUtilService.today
+        // Auto swap date range.
+        if(result.startDate > result.endDate) {
+            def tempStartDate = result.startDate
+            result.startDate = result.endDate
+            result.endDate = tempStartDate
+        }
+        result.includeCompleted = params.includeCompleted = params.includeCompleted ? true:false
+
+        def getMessage = { Map m ->
+            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
+        }
+
+        def formatted = { Date d ->
+            g.formatDate(format: "EEE, dd-MMM-yyyy", date: d)
+        }
+
+        def startOfToday = dateUtilService.today
+        def startOfYesterday = dateUtilService.yesterday
+        def startOfTomorrow = dateUtilService.tomorrow
+        def oneWeekAgo = dateUtilService.oneWeekAgo
+
+        def formattedStartOfToday = formatted(startOfToday)
+        def formattedStartOfYesterday = formatted(startOfYesterday)
+        def formattedStartOfTomorrow = formatted(startOfTomorrow)
+        def formattedOneWeekAgo = formatted(oneWeekAgo)
+
+        def allTasks = {
+            result.taskInstanceList = getTasks(params, result.startDate, result.endDate+1)
+            if(result.taskInstanceList.totalCount > 0) {
+                if(result.startDate == result.endDate)
+                    result.message = getMessage(code:"task.search.text.all.tasks.message",
+                                                                    args:[ formatted(result.startDate) ])
+                else
+                    result.message = getMessage(code:"task.search.text.all.tasks.between.message",
+                                                                    args:[ formatted(result.startDate), formatted(result.endDate) ])
+            }
+            else {
+                if(result.startDate == result.endDate)
+                    result.message = getMessage(code:"task.search.text.all.tasks.none.found",
+                                                                    args:[ formatted(result.startDate) ])
+                else
+                    result.message = getMessage(code:"task.search.text.all.tasks.between.none.found",
+                                                                    args:[ formatted(result.startDate), formatted(result.endDate) ])
+            }
+
+        }
+
+        def personsTasks = {
+            result.taskInstanceList = getPersonsTasks(params, result.person, result.startDate, result.endDate+1)
+            if(result.taskInstanceList.totalCount > 0) {
+                if(result.startDate == result.endDate)
+                    result.message = getMessage(code:"task.search.text.persons.tasks.message",
+                                                                    args:[ result.person, formatted(result.startDate) ])
+                else
+                    result.message = getMessage(code:"task.search.text.persons.tasks.between.message",
+                                                                    args:[ result.person, formatted(result.startDate), formatted(result.endDate) ])
+            }
+            else {
+                if(result.startDate == result.endDate)
+                    result.message = getMessage(code:"task.search.text.persons.tasks.none.found",
+                                                                    args:[ result.person, formatted(result.startDate) ])
+                else
+                    result.message = getMessage(code:"task.search.text.persons.tasks.between.none.found",
+                                                                    args:[ result.person, formatted(result.startDate), formatted(result.endDate) ])
+            }
+
+        }
+
+        def personsImmediateCallouts = {
+            result.taskInstanceList = getPersonsImmediateCallouts(params, result.person, result.startDate, result.endDate+1)
+            if(result.taskInstanceList.totalCount > 0) {
+                if(result.startDate == result.endDate)
+                    result.message = getMessage(code:"task.search.text.persons.immediate.callouts.message",
+                                                                    args:[ result.person, formatted(result.startDate) ])
+                else
+                    result.message = getMessage(code:"task.search.text.persons.immediate.callouts.between.message",
+                                                                    args:[ result.person, formatted(result.startDate), formatted(result.endDate) ])
+            }
+            else {
+                if(result.startDate == result.endDate)
+                    result.message = getMessage(code:"task.search.text.persons.immediate.callouts.none.found",
+                                                                    args:[ result.person, formatted(result.startDate) ])
+                else
+                    result.message = getMessage(code:"task.search.text.persons.immediate.callouts.between.none.found",
+                                                                    args:[ result.person, formatted(result.startDate), formatted(result.endDate) ])
+            }
+
+        }
+
+        switch (result.quickSearch) {
+            case "myTodays":
+                result.quickSearch = "personsTasks"
+                result.startDate = startOfToday
+                result.endDate = startOfToday
+                personsTasks()
+                break
+            case "myYesterdays":
+                result.quickSearch = "personsTasks"
+                result.startDate = startOfYesterday
+                result.endDate = startOfYesterday
+                personsTasks()
+                break
+            case "myTomorrows":
+                result.quickSearch = "personsTasks"
+                result.startDate = startOfTomorrow
+                result.endDate = startOfTomorrow
+                personsTasks()
+                break
+            case "myPastWeek":
+                result.quickSearch = "personsTasks"
+                result.startDate = oneWeekAgo
+                result.endDate = startOfToday
+                personsTasks()
+                break
+            case "personsTasks":
+                personsTasks()
+                break
+            case "personsImmediateCallouts":
+                personsImmediateCallouts()
+                break
+            case "todays":
+                result.quickSearch = "allTasks"
+                result.startDate = startOfToday
+                result.endDate = startOfToday
+                allTasks()
+                break
+            case "yesterdays":
+                result.quickSearch = "allTasks"
+                result.startDate = startOfYesterday
+                result.endDate = startOfToday
+                allTasks()
+                break
+            case "tomorrows":
+                result.quickSearch = "allTasks"
+                result.startDate = startOfTomorrow
+                result.endDate = startOfTomorrow+1
+                allTasks()
+                break
+            case "pastWeek":
+                result.quickSearch = "allTasks"
+                result.startDate = oneWeekAgo
+                result.endDate = startOfTomorrow
+                allTasks()
+                break
+            case "allTasks":
+                allTasks()
+                break
+            default:
+                //case "plannersRange":
+                result.quickSearch = "allTasks"
+                result.startDate = oneWeekAgo
+                result.endDate = startOfToday+15
+                allTasks()
+                break
+        } // switch.
+
+        // Success.
+        return result
+
+    } // getQuickSearch
+
+    /**
+    * Get all tasks that are not in the trash bin, by default today's tasks.
+    * @param params The request params.
+    * @param startDate The start date to get tasks for, defaults to the start of today and is inclusive (greater than or equal to).
+    * @param endDate The end date to get tasks for, defaults to the start of tomorrow and is exclusive (less than).
+    */
+    def getTasks(params, startDate=null, endDate=null) {
+        def paginateParams = [:]
+        paginateParams.max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
+        paginateParams.offset = params?.offset?.toInteger() ?: 0
+
+        def orderBy = ''
+        if(params.sort?.contains('.')) // protect against filterpane bug.
+            params.sort = null
+        if(params.sort && params.order) {
+            def sort = "task." + params.sort
+            def order = (params.order == "asc") ? "asc" : "desc"
+            orderBy = " order by " + sort + ' ' + order
+        }
+        else
+            orderBy = " order by task.taskStatus, task.taskPriority, task.targetStartDate"
+
+        def namedParams = [:]
+        namedParams.startDate = startDate ?: dateUtilService.today
+        namedParams.endDate = endDate ?: dateUtilService.tomorrow
+
+        def baseQuery = "from Task as task \
+                                        where (task.trash = false \
+                                                    and task.targetStartDate < :endDate \
+                                                    and task.targetCompletionDate >= :startDate \
+                                        )"
+
+        def searchQuery = "select distinct task " + baseQuery + orderBy
+        def list = Task.executeQuery(searchQuery, namedParams, paginateParams)
+
+        def countQuery = "select count(distinct task) as taskCount " + baseQuery
+        def totalCount = Task.executeQuery(countQuery, namedParams)[0].toInteger()
+
+        def taskInstanceList = new PagedResultList(list, totalCount)
+        return taskInstanceList
+    } // getPTasks()
+
+    /**
+    * Get a person's tasks, by default current user and today's tasks.
+    * "My tasks and approved tasks that I am assigned to"
+    * @param params The request params.
+    * @param person The person to get tasks for, defaults to current user.
+    * @param startDate The start date to get tasks for, defaults to the start of today and is inclusive (greater than or equal to).
+    * @param endDate The end date to get tasks for, defaults to the start of tomorrow and is exclusive (less than).
+    */
+    def getPersonsTasks(params, person=null, startDate=null, endDate=null) {
+
+        def max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
+        def offset = params?.offset?.toInteger() ?: 0
+
+        def orderBy = ''
+        if(params.sort?.contains('.')) // protect against filterpane bug.
+            params.sort = null
+        if(params.sort && params.order) {
+            def sort = "task." + params.sort
+            def order = (params.order == "asc") ? "asc" : "desc"
+            orderBy = "by " + sort + ' ' + order
+        }
+        else
+            orderBy = "by task.taskPriority, task.targetStartDate, task.taskStatus"
+
+        def q = new HqlBuilder().query {
+
+            select 'count(distinct task) as taskCount'
+            from 'Task as task',
+                    'left join task.assignedPersons as assignedPersonOfTask',
+                    'left join assignedPersonOfTask.person as assignedPerson',
+                    'left join task.assignedGroups as assignedGroupOfTask',
+                    'left join assignedGroupOfTask.personGroup as personGroup',
+                    'left join personGroup.persons as assignedPersonViaGroup',
+                    'left join task.taskModifications as taskModification',
+                    'left join taskModification.person as createdBy',
+                    'left join taskModification.taskModificationType as taskModificationType'
+            where 'task.trash = false'
+                    and 'task.targetStartDate < :endDate'
+                    and 'task.targetCompletionDate >= :startDate'
+                    if(!params.includeCompleted) {
+                        and 'task.taskStatus.id != 3' // Complete.
+                    }
+                    and {
+                        where '(taskModificationType.id = 1 and createdBy = :person and task.leadPerson = :person)' // Created.
+                        or '(task.approved = true and (task.leadPerson = :person or assignedPerson = :person or assignedPersonViaGroup = :person))'
+                    }
+        }
+
+        q.namedParams.person = person ?: authService.currentUser
+        q.namedParams.startDate = startDate ?: dateUtilService.today
+        q.namedParams.endDate = endDate ?: dateUtilService.tomorrow
+
+        def totalCount = Task.executeQuery(q.query, q.namedParams)[0].toInteger()
+
+        q.select = "distinct task"
+        q.order = orderBy
+        def list = Task.executeQuery(q.query, q.namedParams, q.paginateParams)
+
+        def taskInstanceList = new PagedResultList(list, totalCount)
+        return taskInstanceList
+    } // getPersonsTasks()
+
+    /**
+    * Get a person's immediateCallout tasks, by default all users and today's tasks.
+    * @param params The request params.
+    * @param person The person to get tasks for, defaults to null and therefore all immediateCallouts.
+    * @param startDate The start date to get tasks for, defaults to the start of today and is inclusive (greater than or equal to).
+    * @param endDate The end date to get tasks for, defaults to the start of tomorrow and is exclusive (less than).
+    */
+    def getPersonsImmediateCallouts(params, person=null, startDate=null, endDate=null) {
+
+        def max = Math.min(params?.max?.toInteger() ?: 10, paramsMax)
+        def offset = params?.offset?.toInteger() ?: 0
+
+        def orderBy = ''
+        if(params.sort?.contains('.')) // protect against filterpane bug.
+            params.sort = null
+        if(params.sort && params.order) {
+            def sort = "task." + params.sort
+            def order = (params.order == "asc") ? "asc" : "desc"
+            orderBy = "by " + sort + ' ' + order
+        }
+        else
+            orderBy = "by task.taskStatus, task.targetStartDate"
+
+        def q = new HqlBuilder().query {
+
+            select 'count(distinct task) as taskCount'
+            from 'Task as task',
+                    'left join task.taskModifications as taskModification',
+                    'left join taskModification.person as createdBy',
+                    'left join taskModification.taskModificationType as taskModificationType'
+            where 'task.taskType.id = 1' // Immediate Callout.
+                    and 'task.targetStartDate < :endDate'
+                    and 'task.targetCompletionDate >= :startDate'
+                    if(!params.includeCompleted) {
+                        and 'task.taskStatus.id != 3' // Complete.
+                    }
+                    if(person) {
+                        namedParams.person = person
+                        and '( (taskModificationType.id = 1 and createdBy = :person) or task.leadPerson = :person)' // Created or Lead Person.
+                    }
+                    and 'task.trash = false'
+        }
+
+        q.namedParams.startDate = startDate ?: dateUtilService.today
+        q.namedParams.endDate = endDate ?: dateUtilService.tomorrow
+
+        def totalCount = Task.executeQuery(q.query, q.namedParams)[0].toInteger()
+
+        q.select = "distinct task"
+        q.order = orderBy
+        def list = Task.executeQuery(q.query, q.namedParams, q.paginateParams)
+
+        def taskInstanceList = new PagedResultList(list, totalCount)
+        return taskInstanceList
+    } // getPersonsImmediateCallouts()
+
+    /**
+    * Get work done by person and date.
+    * A person ID and date may be specified in params otherwise the current user and today are used.
+    * @param params The request params.
+    * @returns A map containing entries, totalEntries, startOfDay, person, totalHours, totalMinutes.
+    */
+    def getWorkDone(params, locale) {
+        def result = [:]
+        result.person = params.person?.id ? Person.get(params.person.id.toInteger()) : authService.currentUser
+
+        if(params.date_year && params.date_month && params.date_day)
+            result.startOfDay = dateUtilService.makeDate(params.date_year, params.date_month, params.date_day)
+        else
+            result.startOfDay = dateUtilService.today
+
+        result.startOfNextDay = result.startOfDay + 1
+
+        def formattedStartOfDay = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.startOfDay)
+
+        def getMessage = { Map m ->
+            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
+        }
+
+        result.entries = Entry.createCriteria().list() {
+            eq("enteredBy", result.person)
+            ge("dateDone", result.startOfDay)
+            lt("dateDone", result.startOfNextDay)
+            entryType {
+                eq("id", 3L)
+            }
+        } // createCriteria
+
+        result.totalEntries = result.entries.size()
+
+        if(result.totalEntries > 0)
+            result.message = getMessage(code:"task.search.text.work.done.message",
+                                                                args:[result.person, formattedStartOfDay])
+        else
+            result.message = getMessage(code:"task.search.text.work.done.none.found",
+                                                                args:[result.person, formattedStartOfDay])
+
+        result.totalHours = 0
+        result.totalMinutes = 0
+        result.entries.each() {
+            result.totalMinutes += (it.durationHour*60) + it.durationMinute
+        }
+        result.totalHours = (result.totalMinutes / 60).toInteger()
+        result.totalMinutes = result.totalMinutes % 60
+
+        return result
+    } // getWorkDone()
+
+    /**
+    * Get work load by task group and date.
+    * Group ID's and date range may be specified in params otherwise no group and today are used.
+    * @param params The request params.
+    * @returns A map containing the results.
+    */
+    def getWorkLoad(params, locale) {
+        def result = [:]
+        def max = 1000
+
+        // TaskStatus..
+        result.taskStatusList = []
+        if(params.taskStatusList instanceof String)
+            result.taskStatusList << TaskStatus.get(params.taskStatusList.toInteger())
+        else if(params.taskStatusList)
+            result.taskStatusList = TaskStatus.getAll( params.taskStatusList.collect {it.toInteger()} )
+
+        // TaskGroups.
+        result.taskGroups = []
+        if(params.taskGroups instanceof String)
+            result.taskGroups << TaskGroup.get(params.taskGroups.toInteger())
+        else if(params.taskGroups)
+            result.taskGroups = TaskGroup.getAll( params.taskGroups.collect {it.toInteger()} )
+
+        // Start Date.
+        if(params.startDate_year && params.startDate_month && params.startDate_day)
+            result.startDate = dateUtilService.makeDate(params.startDate_year, params.startDate_month, params.startDate_day)
+        else
+            result.startDate = dateUtilService.today
+
+        // End Date.
+        if(params.endDate_year && params.endDate_month && params.endDate_day)
+            result.endDate = dateUtilService.makeDate(params.endDate_year, params.endDate_month, params.endDate_day)
+        else
+            result.endDate = result.startDate
+
+        // Auto swap date range.
+        if(result.startDate > result.endDate) {
+            def tempStartDate = result.startDate
+            result.startDate = result.endDate
+            result.endDate = tempStartDate
+        }
+
+        def formattedStartDate = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.startDate)
+        def formattedEndDate = g.formatDate(format: "EEE, dd-MMM-yyyy", date: result.endDate)
+
+        def getMessage = { Map m ->
+            messageSource.getMessage(m.code, m.args == null ? null : m.args.toArray(), locale)
+        }
+
+        result.tasks = new PagedResultList([], 0)
+
+        if(result.taskGroups && result.taskStatusList) {
+
+            result.tasks = Task.createCriteria().list(max: max) {
+                eq("trash", false)
+                lt("targetStartDate", result.endDate+1)
+                ge("targetCompletionDate", result.startDate)
+                inList("taskStatus", result.taskStatusList)
+                inList("taskGroup", result.taskGroups)
+                order("taskStatus", "asc")
+                order("taskPriority", "asc")
+                order("targetStartDate", "asc")
+                fetchMode("assignedGroups", FM.EAGER)
+                fetchMode("assignedGroups.personGroup", FM.EAGER)
+            } // createCriteria
+
+        }
+
+        result.tasks.list.unique()
+        result.totalHours = 0
+        result.totalMinutes = 0
+        result.workLoadGroups = [:]
+
+        // Exit early!
+        if(result.tasks.totalCount > result.tasks.size()) {
+            result.errorMessage = getMessage(code:"task.search.text.work.load.too.many.results",
+                                                                args:[result.tasks.size(), result.tasks.totalCount])
+            return result
+        }
+        else if(result.tasks.size() > 0)
+            result.message = getMessage(code:"task.search.text.work.load.message",
+                                                                args:[formattedStartDate, formattedEndDate])
+        else
+            result.message = getMessage(code:"task.search.text.work.load.none.found",
+                                                                args:[formattedStartDate, formattedEndDate])
+
+        // Collect all assignedGroups.
+        def assignedGroups = []
+        for(task in result.tasks) {
+            for(assignedGroup in task.assignedGroups) {
+                assignedGroups << assignedGroup
+            }
+        }
+
+        // Calculate work load for each personGroup and minute totals.
+        def tempHours = 0
+        def tempMinutes = 0
+        def personGroup
+        for(assignedGroup in assignedGroups) {
+            personGroup = assignedGroup.personGroup
+            if(!result.workLoadGroups.containsKey(personGroup)) {
+                result.workLoadGroups[personGroup] = [hours: 0, minutes: 0]
+            }
+
+            tempMinutes = (assignedGroup.estimatedHour*60) + assignedGroup.estimatedMinute
+            result.totalMinutes += tempMinutes
+            result.workLoadGroups[personGroup].minutes += tempMinutes
+        }
+
+        // Resolve totals and sort.
+        result.workLoadGroups.each { workLoadGroup ->
+            workLoadGroup.value.hours =  (workLoadGroup.value.minutes / 60).toInteger()
+            workLoadGroup.value.minutes = workLoadGroup.value.minutes % 60
+        }
+        result.workLoadGroups = result.workLoadGroups.sort { p1, p2 -> p1.key.name.compareToIgnoreCase(p2.key.name) }
+        result.totalHours = (result.totalMinutes / 60).toInteger()
+        result.totalMinutes = result.totalMinutes % 60
+
+        // Success.
+        return result
+    } // getWorkLoad()
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/services/TaskService.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/services/TaskService.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/services/TaskService.groovy	(revision 753)
@@ -0,0 +1,1000 @@
+import grails.util.Environment
+
+/**
+* Provides a service class for the Task domain class.
+*
+*/
+class TaskService {
+
+    boolean transactional = false
+
+    def authService
+    def dateUtilService
+    def authenticateService
+    def assignedGroupService
+    def assignedPersonService
+
+    /**
+    * Determines and returns a possible parent list for a task.
+    * @todo Create and use another method that limits the results to say the latest 20 or 100 tasks?
+    * @param taskInstance The task to use when determining the possible parent list.
+    * @returns A list of the possible parents.
+    */
+    def possibleParentList(taskInstance) {
+        def criteria = taskInstance.createCriteria()
+        def possibleParentList = criteria {
+            and {
+                notEqual('trash', true)
+                notEqual('id', taskInstance.id)
+                taskInstance.subTasks.each() { notEqual('id', it.id) }
+                }
+        }
+    }
+
+    /**
+    * Determines and returns a list of possible task types for scheduled tasks.
+    * @returns A list of the possible task types.
+    */
+    def getScheduledTaskTypes() {
+        def criteria = TaskType.createCriteria()
+        def scheduledTaskTypes = criteria {
+            and {
+                eq('isActive', true)
+                gt('id', 2L)
+                }
+        }
+    }
+
+    /**
+    * Determines and returns a list of parentPM tasks for an asset.
+    * @param asset The asset to get parentPM tasks for.
+    * @returns A list of the possible task types.
+    */
+    def getParentPMs(asset) {
+        def parentPMs = Task.withCriteria {
+                                                eq("primaryAsset", asset)
+                                                taskType {
+                                                    idEq(6L)
+                                                }
+                                                maxResults(1000)
+                                        }
+    }
+
+    /**
+    * Determines and returns a list of possible task priorites for Scheduled tasks.
+    * @returns A list of the possible task priorites.
+    */
+    def getScheduledTaskPriorities() {
+        def criteria = TaskPriority.createCriteria()
+        def scheduledTaskPriorities = [:]
+        scheduledTaskPriorities.list = criteria {
+            and {
+                eq('isActive', true)
+                gt('id', 1L)
+                }
+        }
+        scheduledTaskPriorities.default = scheduledTaskPriorities.list.find { it.id == 4L } //  1-Normal.
+        return scheduledTaskPriorities
+    }
+
+    /**
+    * Determines and returns a list of possible task priorites for Unscheduled tasks.
+    * @returns A map containing a list of the possible task priorites and the default priority.
+    */
+    def getUnscheduledTaskPriorities() {
+        def criteria = TaskPriority.createCriteria()
+        def unscheduledTaskPriorities = [:]
+        unscheduledTaskPriorities.list = criteria {
+            and {
+                eq('isActive', true)
+                lt('id', 5L)
+                ne('id', 1L)
+            }
+        }
+        unscheduledTaskPriorities.default = unscheduledTaskPriorities.list.find { it.id == 3L } // 2-High.
+        return unscheduledTaskPriorities
+    }
+
+    /**
+    * Creates a new task with the given params.
+    * @param params The params to use when creating the new task.
+    * @returns A map containing result.error (if any error) and result.taskInstance.
+    */
+    def save(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            def taskInstance = new Task(params)
+            result.taskInstance = taskInstance
+
+            // Set taskStatus if not supplied.
+            if(!params.taskStatus)
+                taskInstance.taskStatus = TaskStatus.read(1) // Not Started
+
+            // Set budgetStatus if not supplied.
+            if(!params.taskBudgetStatus) {
+                if(taskInstance.taskType?.id == 1 || taskInstance.taskType?.id == 2) // Immediate Callout or Unsheduled Breakin.
+                    taskInstance.taskBudgetStatus = TaskBudgetStatus.read(1) // Unplanned.
+                else
+                    taskInstance.taskBudgetStatus = TaskBudgetStatus.read(2) // Planned.
+            }
+
+            if(result.taskInstance.parentTask?.trash)
+                return fail(field:"parentTask", code:"task.operationNotPermittedOnTaskInTrash")
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                return fail(code:"default.create.failure")
+
+            def taskModification = new TaskModification(person: authService.currentUser,
+                                                taskModificationType: TaskModificationType.get(1),
+                                                task: taskInstance)
+
+            if(taskModification.hasErrors() || !taskModification.save())
+                return fail(field:"taskModifications", code:"task.modifications.failedToSave")
+
+            //Add the assignedGroups, provided by a new ArrayList(task.assignedGroups)
+            if(params.assignedGroups) {
+                def assignedGroupsResult
+                def assignedGroupParams = [:]
+                params.assignedGroups.each() {
+
+                    assignedGroupParams = [personGroup: it.personGroup,
+                                                                task: taskInstance,
+                                                                estimatedHour: it.estimatedHour,
+                                                                estimatedMinute: it.estimatedMinute]
+
+                    assignedGroupsResult = assignedGroupService.save(assignedGroupParams)
+
+                    if(assignedGroupsResult.error)
+                        return fail(field:"assignedGroups", code:"task.assignedGroups.failedToSave")
+
+                }
+            }
+
+            //Add the assignedPersons, provided by a new ArrayList(task.assignedPersons)
+            if(params.assignedPersons) {
+                def assignedPersonsResult
+                def assignedPersonsParams = [:]
+                params.assignedPersons.each() {
+
+                    assignedPersonsParams = [person: it.person,
+                                                                task: taskInstance,
+                                                                estimatedHour: it.estimatedHour,
+                                                                estimatedMinute: it.estimatedMinute]
+
+                    assignedPersonsResult = assignedPersonService.save(assignedPersonsParams)
+
+                    if(assignedPersonsResult.error)
+                        return fail(field:"assignedPersons", code:"task.assignedPersons.failedToSave")
+
+                }
+            }
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    } // end save()
+
+    /**
+    * Creates a subTask copying sane attributes from the parentTask unless otherwise specified in params.
+    * The targetStartDate and targetCompletionDate default to today since that is the sane thing to do.
+    * The taskProcedure is only assigned to the sub task if supplied in params.
+    * The assignedPersons and assignedGroups are only added to the sub task if supplied in params.
+    * The positiveFault property is never set on the subTask.
+    * Collections in params must be supplied as new ArrayList's.
+    * This method is not intended to be a copyTask method.
+    * There should be no reason to copy tasks, recurrence can be used to create similar tasks.
+    * @param parentTask The parent task to get attributes from, also set as the parent.
+    * @param params Overrides the parent task values if specified.
+    * @returns A map containing result.error=true (if any error) and result.taskInstance.
+    */
+    def createSubTask(parentTask, params = [:]) {
+
+        def result = [:]
+
+        //Make our new Task a subTask and set the required properties.
+        def p = [:]
+        p.parentTask = parentTask
+        p.description = params.description ?: parentTask.description
+        p.comment = params.comment ?: parentTask.comment
+        p.targetStartDate = params.targetStartDate ?: dateUtilService.today
+        p.targetCompletionDate = params.targetCompletionDate ?: dateUtilService.today
+
+        p.safetyRequirement = params.safetyRequirement ?: parentTask.safetyRequirement
+        p.regulatoryRequirement = params.regulatoryRequirement ?: parentTask.regulatoryRequirement
+        p.mandatoryRequirement = params.mandatoryRequirement ?: parentTask.mandatoryRequirement
+
+        p.taskGroup = params.taskGroup ?: parentTask.taskGroup
+        p.taskStatus = TaskStatus.get(1) // A new subTask must always be "Not Started".
+        p.taskPriority = parentTask.taskPriority
+
+        p.taskType = params.taskType ?: parentTask.taskType
+         // Convert "Parent PM" tasks to "Preventative Maintenance" tasks.
+        if(p.taskType.id == 6)
+            p.taskType = TaskType.get(4)
+
+        p.leadPerson = params.leadPerson ?: parentTask.leadPerson
+        p.primaryAsset = params.primaryAsset ?: parentTask.primaryAsset
+        p.associatedAssets = params.associatedAssets ?: new ArrayList(parentTask.associatedAssets) // Collection.
+
+        // Supplied by recurring tasks.
+        if(params.taskProcedure) p.taskProcedure = params.taskProcedure
+        if(params.assignedGroups) p.assignedGroups = params.assignedGroups // Collection.
+        if(params.assignedPersons) p.assignedPersons = params.assignedPersons // Collection.
+
+        // trash: A new subTask must always have trash=false, which is already the domain class default.
+
+        // These would be considered copying, hence not done.
+        // taskRecurringSchedule, entries, taskModifications, subTasks, inventoryMovements.
+
+        // Create the sub task and return the result.
+        result = save(p)
+
+        // Approve.
+        if(!result.error && parentTask.approved) {
+            p = [:]
+            p.id = result.taskInstance.id
+            approve(p)
+        }
+
+        // Success.
+        return result
+
+    } // end createSubTask()
+
+    /**
+    * In production tasks are NEVER deleted, only the trash flag is set!
+    * However during testing it may be required to delete a task and that
+    * is why this method exists.
+    */
+    def delete(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            if(Environment.current == Environment.PRODUCTION)
+                return fail(code:"task.delete.failure.production")
+
+            result.taskInstance = Task.get(params.id)
+
+            if(!result.taskInstance)
+                return fail(code:"default.not.found")
+
+            // Handle taskModifications.
+            def taskModifications = TaskModification.findAllByTask(result.taskInstance)
+            taskModifications.each() {
+                result.taskInstance.removeFromTaskModifications(it)
+                it.delete()
+            }
+
+            // Handle assignedPersons.
+            def taskAssignedPersons = AssignedPerson.findAllByTask(result.taskInstance)
+            taskAssignedPersons.each() {
+                result.taskInstance.removeFromAssignedPersons(it)
+                it.delete()
+            }
+
+            // Handle assignedGroups.
+            def taskAssignedGroups = AssignedGroup.findAllByTask(result.taskInstance)
+            taskAssignedGroups.each() {
+                result.taskInstance.removeFromAssignedGroups(it)
+                it.delete()
+            }
+
+            if(result.error)
+                return result
+
+            try {
+                result.taskInstance.delete(flush:true)
+                return result //Success.
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                return fail(code:"default.delete.failure")
+            }
+
+        } // end withTransaction
+    } // delete()
+
+    /**
+    * Creates a new task entry.
+    * @param params The params to use when creating the new entry.
+    * @returns A map containing result.error=true (if any error), result.entryInstance and result.taskId.
+    */
+    def saveEntry(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Entry", params.id] ]
+                return result
+            }
+
+            result.entryInstance = new Entry(params)
+            result.entryInstance.enteredBy = authService.currentUser
+
+            def taskInstance
+            if(result.entryInstance.task?.id) {
+                result.taskId = result.entryInstance.task.id
+                taskInstance = Task.lock(result.entryInstance.task.id)
+            }
+
+            if(!taskInstance)
+                return fail(field:"task", code:"task.notFound")
+
+            if(result.entryInstance.hasErrors() || !result.entryInstance.save())
+                return fail(code:"default.create.failure")
+
+            if(taskInstance.taskStatus.id == 3)
+                return fail(field:"task", code:"task.operationNotPermittedOnCompleteTask")
+
+            // Check for authorisation on recurring tasks.
+            if(taskInstance.taskRecurringSchedule) {
+                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
+                    return fail(field:"task", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+            }
+
+            // If task status is "Not Started" and entry type is "Work Done" and time has been booked.
+            // Then we create the started modification and set task status.
+            if(taskInstance.taskStatus.id == 1 && result.entryInstance.entryType.id == 3
+                && (result.entryInstance.durationHour + result.entryInstance.durationMinute > 0)) {
+
+                // Create the "Started" task modification, this provides the "Actual Started Date".
+                def taskModification = new TaskModification(person: authService.currentUser,
+                                                        taskModificationType: TaskModificationType.read(2),
+                                                        task: taskInstance)
+
+                if(taskModification.hasErrors() || !taskModification.save())
+                    return fail(field:"task", code:"task.modifications.failedToSave")
+
+                // Set task status to "In Progress".
+                taskInstance.taskStatus = TaskStatus.read(2)
+
+                if(taskInstance.hasErrors() || !taskInstance.save())
+                    return fail(field:"task", code:"task.failedToSave")
+            }
+
+            // Success.
+            return result
+
+        } // end withTransaction
+    } // end saveEntry()
+
+    /**
+    * Updates an existing task.
+    * @param params The params to update for task with id of params.id.
+    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
+    */
+    def update(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            result.taskInstance = Task.get(params.id)
+
+            if(!result.taskInstance)
+                return fail('id', "task.notFound")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.taskInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            // Check for authorisation on recurring tasks.
+            if(result.taskInstance.taskRecurringSchedule) {
+                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
+                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+            }
+
+            result.taskInstance.properties = params
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person:authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(3),
+                                                    task: result.taskInstance)
+
+            if(taskModification.hasErrors() || !taskModification.save())
+                return fail(code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end update()
+
+    /**
+    * Completes an existing task.
+    * @param params The params for task with id of params.id.
+    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
+    */
+    def complete(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            result.taskInstance = Task.get(params.id)
+
+            if(!result.taskInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.taskInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            // Check for authorisation on recurring tasks.
+            if(result.taskInstance.taskRecurringSchedule) {
+                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
+                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+            }
+
+            result.taskInstance.taskStatus = TaskStatus.get(3)
+            result.taskInstance.attentionFlag = false
+            result.taskInstance.taskRecurringSchedule?.enabled = false
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person:authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(4),
+                                                    task: result.taskInstance)
+
+
+            if(taskModification.hasErrors() || !taskModification.save())
+                return fail(code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end complete()
+
+    /**
+    * Sets the attentionFlag on an existing task.
+    * @param params The params for task with id of params.id.
+    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
+    */
+    def setAttentionFlag(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            result.taskInstance = Task.get(params.id)
+
+            if(!result.taskInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.taskInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            // Check for authorisation on recurring tasks.
+            if(result.taskInstance.taskRecurringSchedule) {
+                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
+                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+            }
+
+            result.taskInstance.attentionFlag = true
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person:authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(12),
+                                                    task: result.taskInstance)
+
+            if(taskModification.hasErrors() || !taskModification.save())
+                return fail(code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end flag()
+
+    /**
+    * Clears the attentionFlag on an existing task.
+    * @param params The params for task with id of params.id.
+    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
+    */
+    def clearAttentionFlag(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            result.taskInstance = Task.get(params.id)
+
+            if(!result.taskInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.taskInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            // Check for authorisation on recurring tasks.
+            if(result.taskInstance.taskRecurringSchedule) {
+                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
+                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+            }
+
+            result.taskInstance.attentionFlag = false
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person:authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(13),
+                                                    task: result.taskInstance)
+
+            if(taskModification.hasErrors() || !taskModification.save())
+                return fail(code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end clearFlag()
+
+    /**
+    * Reopens an existing task.
+    * @param params The params for task with id of params.id.
+    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
+    */
+    def reopen(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            result.taskInstance = Task.get(params.id)
+
+            if(!result.taskInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.taskInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            // Check for authorisation on recurring tasks.
+            if(result.taskInstance.taskRecurringSchedule) {
+                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
+                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+            }
+
+            def isInProgress = false
+            result.taskInstance.entries.each() {
+                if(it.entryType.id == 3 && (it.durationHour + it.durationMinute > 0) )
+                    isInProgress = true
+            }
+
+            if(isInProgress)
+                result.taskInstance.taskStatus = TaskStatus.read(2) // In Progress
+            else
+                result.taskInstance.taskStatus = TaskStatus.read(1) // Not Started
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person:authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(5),
+                                                    task: result.taskInstance)
+
+            if(taskModification.hasErrors() || !taskModification.save())
+                return fail(code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end reopen()
+
+    /**
+    * Move a task to the trash.
+    * @param params The params for task with id of params.id.
+    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
+    */
+    def trash(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            result.taskInstance = Task.get(params.id)
+
+            if(!result.taskInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.taskInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            // Check for authorisation on recurring tasks.
+            if(result.taskInstance.taskRecurringSchedule) {
+                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
+                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+            }
+
+            result.taskInstance.trash = true
+            result.taskInstance.attentionFlag = false
+            result.taskInstance.taskRecurringSchedule?.enabled = false
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person:authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(6),
+                                                    task: result.taskInstance)
+
+            if(taskModification.hasErrors() || !taskModification.save())
+                return fail(code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end trash()
+
+    /**
+    * Restore a task from the trash.
+    * @param params The params for task with id of params.id.
+    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
+    */
+    def restore(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            result.taskInstance = Task.get(params.id)
+
+            if(!result.taskInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.taskInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            // Check for authorisation on recurring tasks.
+            if(result.taskInstance.taskRecurringSchedule) {
+                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
+                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+            }
+
+            result.taskInstance.trash = false
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person:authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(7),
+                                                    task: result.taskInstance)
+
+            if(taskModification.hasErrors() || !taskModification.save())
+                return fail(code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end restore()
+
+    /**
+    * Approve a task.
+    * @param params The params for task with id of params.id.
+    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
+    */
+    def approve(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            result.taskInstance = Task.get(params.id)
+
+            if(!result.taskInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.taskInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            // Check for authorisation on recurring tasks.
+            if(result.taskInstance.taskRecurringSchedule) {
+                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
+                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+            }
+
+            result.taskInstance.approved = true
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person:authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(8),
+                                                    task: result.taskInstance)
+
+            if(taskModification.hasErrors() || !taskModification.save())
+                return fail(code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end approve()
+
+    /**
+    * Remove a previously given approval from a task.
+    * @param params The params for task with id of params.id.
+    * @returns A map containing result.error (if any error) and result.taskInstance (if available).
+    */
+    def renegeApproval(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            result.taskInstance = Task.get(params.id)
+
+            if(!result.taskInstance)
+                return fail(code:"default.not.found")
+
+            // Optimistic locking check.
+            if(params.version) {
+                if(result.taskInstance.version > params.version.toLong())
+                    return fail(field:"version", code:"default.optimistic.locking.failure")
+            }
+
+            // Check for authorisation on recurring tasks.
+            if(result.taskInstance.taskRecurringSchedule) {
+                if(!authenticateService.ifAnyGranted('ROLE_AppAdmin,ROLE_Manager,ROLE_TaskManager'))
+                    return fail(field:"taskRecurringSchedule", code:"task.operationNotPermittedOnRecurringTaskWithoutAuth")
+            }
+
+            result.taskInstance.approved = false
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                return fail(code:"default.update.failure")
+
+            def taskModification = new TaskModification(person:authService.currentUser,
+                                                    taskModificationType: TaskModificationType.get(9),
+                                                    task: result.taskInstance)
+
+            if(taskModification.hasErrors() || !taskModification.save())
+                return fail(code:"task.modifications.failedToSave")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    }  // end renegeApproval()
+
+    /**
+    * Creates a new unscheduled breakin task with the given params.
+    * @param params The params to use when creating the new task.
+    * @returns A map containing result.error (if any error) and result.taskInstance.
+    */
+    def saveUnscheduled(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            // If not supplied.
+            if(!params.taskStatus)
+                params.taskStatus = TaskStatus.get(1) // Not Started.
+
+            result.taskInstance = new Task(params)
+
+            // Always for an unscheduled breakin..
+            result.taskInstance.taskType = TaskType.get(2) // Unscheduled Breakin.
+            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                fail(code:"default.create.failure")
+
+            if(!result.error) {
+                def taskModification = new TaskModification(person: authService.currentUser,
+                                                                taskModificationType: TaskModificationType.get(1), // Created.
+                                                                task: result.taskInstance)
+
+                if(taskModification.hasErrors() || !taskModification.save())
+                    fail(field:"taskModifications", code:"task.modifications.failedToSave")
+            }
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    } // end saveUnscheduled()
+
+    /**
+    * Creates a new immediate callout task with the given params.
+    * @param params The params to use when creating the new task.
+    * @returns A map containing result.error (if any error) and result.taskInstance.
+    */
+    def saveImmediateCallout(params) {
+        Task.withTransaction { status ->
+            def result = [:]
+
+            def fail = { Map m ->
+                status.setRollbackOnly()
+                if(result.taskInstance && m.field)
+                    result.taskInstance.errors.rejectValue(m.field, m.code)
+                result.error = [ code: m.code, args: ["Task", params.id] ]
+                return result
+            }
+
+            // If not supplied.
+            if(!params.taskStatus)
+                params.taskStatus = TaskStatus.get(1) // Not Started.
+
+            result.taskInstance = new Task(params)
+
+            // Always for an immediate callout.
+            result.taskInstance.taskType = TaskType.get(1) // Immediate Callout.
+            result.taskInstance.taskBudgetStatus = TaskBudgetStatus.get(1) // Unplanned.
+            result.taskInstance.taskPriority = TaskPriority.get(1) // Immediate.
+            result.taskInstance.taskGroup = TaskGroup.get(1) // Engineering Activites.
+            result.taskInstance.approved = true
+            result.taskInstance.leadPerson = authService.currentUser
+            result.taskInstance.targetCompletionDate = result.taskInstance.targetStartDate
+
+            if(result.taskInstance.hasErrors() || !result.taskInstance.save())
+                fail(code:"default.create.failure")
+
+            if(!result.error) {
+                def taskModification = new TaskModification(person: authService.currentUser,
+                                                                taskModificationType: TaskModificationType.get(1), // Created.
+                                                                task: result.taskInstance)
+
+                if(taskModification.hasErrors() || !taskModification.save())
+                    fail(field:"taskModifications", code:"task.modifications.failedToSave")
+            }
+
+            def productionReference
+            if(params.entryFault.productionReference.id.isLong())
+                productionReference = ProductionReference.get(params.entryFault.productionReference.id.toLong())
+
+            def faultParams = [task: result.taskInstance,
+                                            entryType: EntryType.get(1),
+                                            comment: params.entryFault.comment,
+                                            dateDone: result.taskInstance.targetStartDate,
+                                            productionReference: productionReference,
+                                            durationHour: params.entryFault.durationHour,
+                                            durationMinute: params.entryFault.durationMinute]
+            def faultResult = saveEntry(faultParams)
+            result.entryFaultInstance = faultResult.entryInstance
+
+            def causeParams = [task: result.taskInstance,
+                                            entryType: EntryType.get(2),
+                                            dateDone: result.taskInstance.targetStartDate,
+                                            comment: params.entryCause.comment]
+            def causeResult = saveEntry(causeParams)
+            result.entryCauseInstance = causeResult.entryInstance
+
+            def workDoneParams = [task: result.taskInstance,
+                                                    entryType: EntryType.get(3),
+                                                    comment: params.entryWorkDone.comment,
+                                            dateDone: result.taskInstance.targetStartDate,
+                                                    durationHour: params.entryWorkDone.durationHour,
+                                                    durationMinute: params.entryWorkDone.durationMinute]
+            def workDoneResult = saveEntry(workDoneParams)
+            result.entryWorkDoneInstance = workDoneResult.entryInstance
+
+            if(result.error)
+                return result
+
+            if(causeResult.error)
+                return fail(code: "default.create.failure")
+
+            if(faultResult.error)
+                return fail(code: "default.create.failure")
+
+            if(workDoneResult.error)
+                return fail(code: "default.create.failure")
+
+            // Success.
+            return result
+
+        } //end withTransaction
+    } // end saveImmediateCallout()
+
+} // end TaskService
Index: branches/features/taskProcedureRework/grails-app/taglib/AssetTreeTagLib.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/taglib/AssetTreeTagLib.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/taglib/AssetTreeTagLib.groovy	(revision 753)
@@ -0,0 +1,32 @@
+/**
+* Asset Tree tags.
+* Specific to gnuMims hence the namespace.
+*/
+class AssetTreeTagLib {
+    static namespace = 'gnuMims'
+
+    def js = new JsUtilService()
+    def assetTreeService
+
+    /**
+    * Include required javascript and do setup here.
+    */
+    def resources = { attrs ->
+        out << g.javascript(src: "assetTree.js")
+    }
+
+    /**
+    * Button that opens the asset tree pane and calls the javascript to populate it.
+    */
+    def assetTreeButton = { attrs ->
+        out << assetTreeService.buildAssetTreeButton(attrs)
+    } // assetTreeButton
+
+    /**
+    * The asset tree pane, ready for populating by an ajax call to AssetTreeSevice.
+    */
+    def assetTreePane = { attrs ->
+        out << assetTreeService.buildAssetTreePane(attrs)
+    }
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/taglib/CustomTagLib.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/taglib/CustomTagLib.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/taglib/CustomTagLib.groovy	(revision 753)
@@ -0,0 +1,240 @@
+
+/**
+* General use custom tags.
+* Some are taken from http://www.grails.org/Contribute+a+Tag#checkBoxList
+*/
+class CustomTagLib {
+    static namespace = 'custom'
+
+    def resources = { attrs ->
+        ///@todo: should include our javascript and do setup here.
+    }
+
+    /**
+    * Checkbox list that can be used as a more user-friendly alternative to a multiselect list box.
+     * Usage:
+     * To map the selected ids to corresponding domain objects,
+     * an additional set method is required in the containing domain class:
+     *       //  This additional setter is used to convert the checkBoxList string or string array
+     *       //  of ids selected to the corresponding domain objects.
+     *       public void setAssetSubItemsFromCheckBoxList(ids) {
+     *           def idList = []
+     *           if(ids instanceof String) {
+     *                   if(ids.isInteger())
+     *                       idList << ids.toInteger()
+     *           }
+     *           else {
+     *               ids.each() {
+     *                   if(it.isInteger())
+     *                       idList << it.toInteger()
+     *               }
+     *           }
+     *           this.assetSubItems = idList.collect { AssetSubItem.get( it ) }
+     *       }
+     *
+     * Then a line in the controller:
+     *      assetInstance.setAssetSubItemsFromCheckBoxList(params.assetSubItems)
+     *
+     * Fields:
+     *    name - the property name.
+     *    from - the list to select from.
+     *    value - the current value.
+     *    optionKey - the key to use.
+     *    sortBy - (optional) the attribute to sort the from list by.
+     *    displayFields - (optional) defaults to the objects toString()
+     *    displayFieldsSeparator - (optional) defaults to a space.
+     *    linkController - (optional, requires linkAction.) the controller to use for a link to the objects in the checkBoxList.
+     *    linkAction - (optional, requires linkController.) the action to use for a link to the objects in the checkBoxList.
+     *
+     * Example:
+     *    <!--
+     *    <custom:checkBoxList name="assetSubItems"
+     *                                    from="${AssetSubItem.list()}"
+     *                                    value="${assetInstance?.assetSubItems.collect{it.id}}"
+     *                                    optionKey="id"
+     *                                    sortBy="description"
+     *                                    displayFields="['id', 'name']"
+     *                                    displayFieldsSeparator=', '
+     *                                    linkController="assetSubItemDetailed"
+     *                                    linkAction="show"/>
+     *    -->
+     *
+     */
+
+    def checkBoxList = {attrs, body ->
+
+        def from = attrs.from
+        def value = attrs.value
+        def cname = attrs.name
+        def isChecked, ht, wd, style, html
+
+        def sortBy = attrs.sortBy
+        def displayFields = attrs.displayFields
+        def displayFieldsSeparator = attrs.displayFieldsSeparator ?: ' '
+        def linkController = attrs.linkController
+        def linkAction = attrs.linkAction
+
+        def displayValue = " "
+
+        // sets the style to override height and/or width if either of them
+        // is specified, else the default from the CSS is taken
+        style = "style='"
+        if(attrs.height)
+            style += "height:${attrs.height};"
+        if(attrs.width)
+            style += "width:${attrs.width};"
+        if(style.length() == "style='".length())
+            style = ""
+        else
+            style += "'" // closing single quote
+
+        html = "<ul class='CheckBoxList' " + style + ">"
+
+        out << html
+
+        if(sortBy)
+            from.sort { p1, p2 -> p1[sortBy].compareToIgnoreCase(p2[sortBy]) }
+
+        from.each { obj ->
+
+            displayValue = " "
+
+            if(linkController && linkAction)
+                   displayValue += "<a href=\"${createLink(controller: linkController, action: linkAction, id: obj.id).encodeAsHTML()}\">"
+
+            if(displayFields) {
+                displayValue += displayFields.collect { obj[it] }.join(displayFieldsSeparator)
+            }
+            else displayValue += obj // use the obj's default toString()
+
+            if(linkController && linkAction)
+                displayValue += "</a>"
+
+            // if we wanted to select the checkbox using a click anywhere on the label (also hover effect)
+            // but grails does not recognize index suffix in the name as an array:
+            // cname = "${attrs.name}[${idx++}]"
+            // and put this inside the li: <label for='$cname'>...</label>
+
+            isChecked = (value?.contains(obj."${attrs.optionKey}"))? true: false
+
+            out << "<li>" << checkBox(name:cname, value:obj."${attrs.optionKey}", checked: isChecked) << displayValue << "</li>"
+        }
+
+        out << "</ul>"
+
+    } // checkBoxList
+
+    def sortableColumnWithImg = { attrs, body ->
+        def writer = out
+        if(!attrs.property)
+            throwTagError("Tag [sortableColumn] is missing required attribute [property]")
+
+//         if(!attrs.title && !attrs.titleKey)
+//             throwTagError("Tag [sortableColumn] is missing required attribute [title] or [titleKey]")
+
+        def property = attrs.remove("property")
+        def action = attrs.action ? attrs.remove("action") : (actionName ?: "list")
+
+        def defaultOrder = attrs.remove("defaultOrder")
+        if(defaultOrder != "desc") defaultOrder = "asc"
+
+        // current sorting property and order
+        def sort = params.sort
+        def order = params.order
+
+        // add sorting property and params to link params
+        def linkParams = [:]
+        if(params.id) linkParams.put("id",params.id)
+        if(attrs.params) linkParams.putAll(attrs.remove("params"))
+        linkParams.sort = property
+
+        // determine and add sorting order for this column to link params
+        attrs.class = (attrs.class ? "${attrs.class} sortable" : "sortable")
+        if(property == sort) {
+            attrs.class = attrs.class + " sorted " + order
+            if(order == "asc")
+                linkParams.order = "desc"
+            else
+                linkParams.order = "asc"
+        }
+        else
+            linkParams.order = defaultOrder
+
+        // determine column title
+//         def title = attrs.remove("title")
+//         def titleKey = attrs.remove("titleKey")
+//         if(titleKey) {
+//             if(!title) title = titleKey
+//             def messageSource = grailsAttributes.getApplicationContext().getBean("messageSource")
+//             def locale = RCU.getLocale(request)
+// 
+//             title = messageSource.getMessage(titleKey, null, title, locale)
+//         }
+
+        // Image.
+        def img = "<img "
+        def imgAttrs = [:]
+        imgAttrs.src = attrs.remove("imgSrc")
+        imgAttrs.alt = attrs.remove("imgAlt")
+        imgAttrs.title = attrs.remove("imgTitle")
+        imgAttrs.each { k, v ->
+            if(v)
+                img += "${k}=\"${v.encodeAsHTML()}\" "
+        }
+        img += "/>"
+
+        writer << "<th "
+
+        // process remaining attributes
+        attrs.each { k, v ->
+            writer << "${k}=\"${v.encodeAsHTML()}\" "
+        }
+        writer << ">${link(action:action, params:linkParams) { img } }"
+        writer << "</th>"
+
+    } // sortableColumnWithImg
+
+    /**
+    * Customised version of jasperButton as found in jaser plugin.
+     * custom:jasperButtons is intended to be wrapped by g:jasperForm
+     */
+    def jasperButtons = {attrs ->
+        if(!attrs['format']){throw new Exception(message(code:"jasper.taglib.missingAttribute", args:'format'))}
+        if(!attrs['jasper']){throw new Exception(message(code:"jasper.taglib.missingAttribute", args:'jasper'))}
+        String jasper = attrs['jasper']
+        String buttonClass = attrs['class'] ?:  "jasperButton"
+        String format = attrs['format'].toUpperCase()
+        String text = attrs['text']
+        String heightAttr = attrs['height'] ? ' height="' + attrs['height'] + '"' : '' // leading space on purpose
+        String imgSrc = ''
+        String delimiter = attrs['delimiter'] ?: "|"
+        String delimiterBefore = attrs['delimiterBefore'] ?: delimiter
+        String delimiterAfter = attrs['delimiterAfter'] ?: delimiter
+
+        out << '''
+                    <script type="text/javascript">
+                        function submit_jasperForm(name, fmt) {
+                            var jasperForm = document.getElementsByName(name).item(0)
+                            jasperForm._format.value = fmt;
+                            jasperForm.submit();
+                            return false;
+                        }
+                    </script>
+                    '''
+
+        out << delimiterBefore
+
+        attrs['format'].toUpperCase().split(",").eachWithIndex { it, i ->
+            if (i > 0) out << delimiter
+            imgSrc = g.resource(plugin:"jasper", dir:'images/icons', file:"${it.trim()}.gif")
+            def fmt = it.trim()
+            out << """
+                        <a href="#" class="${buttonClass}" title="${it.trim()}" onClick="return submit_jasperForm('${jasper}', '${fmt}')">
+                        <img border="0" src="${imgSrc}"${heightAttr} /></a>
+                        """
+        }
+
+        out << delimiterAfter
+    } // jasperButtons
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/taglib/JsUtilTagLib.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/taglib/JsUtilTagLib.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/taglib/JsUtilTagLib.groovy	(revision 753)
@@ -0,0 +1,58 @@
+
+/**
+* JsUtil tags.
+* Javascript Utility tags.
+*/
+class JsUtilTagLib {
+    static namespace = 'jsUtil'
+
+    def js = new JsUtilService()
+
+    /**
+    * Resources.
+     * To be included in the page head tag.
+    */
+    def resources = { attrs ->
+        out << g.javascript(src: "jsUtil.js")
+    }
+
+    /**
+    * Toggle the visibility of an html element and update an image.
+    * @param toggleId The html id of the element to toggle.
+    * @param imageId The html id to apply to the image.
+    * @param openImgUrl The url to apply as the image src when toggled element is visible.
+    * @param closedImgUrl The url to apply as the image src when toggled element is hidden.
+    * @param effect The effect to apply, 'fade' uses the fade/appear effect while the default is to just toggle.
+    * @param text The text, if any, to display.
+    * @param useDiv Whether or not to use a wrapping div, default is 'true'.
+    */
+    def toggleControl = { attrs ->
+        def mkp = new groovy.xml.MarkupBuilder(out) //this line will be unnecessary in versions of Grails after version 1.2
+
+        def toggleJs
+
+        // Do we want to fade/appear or just toggle.
+        if(attrs.effect == "fade")
+            toggleJs = js.toggleWithImgAndEffect(attrs.toggleId, attrs.imageId, attrs.openImgUrl, attrs.closedImgUrl)
+        else
+            toggleJs = js.toggleWithImg(attrs.toggleId, attrs.imageId, attrs.openImgUrl, attrs.closedImgUrl)
+
+        if(attrs.useDiv == 'false') {
+            mkp.a( href: toggleJs ) {
+                    yieldUnescaped(attrs.text)
+                    img(id: attrs.imageId, src: attrs.closedImgUrl, alt: "Show")
+            } // mkp
+
+        }
+        else {
+            mkp.div() {
+                a( href: toggleJs ) {
+                    yieldUnescaped(attrs.text)
+                    img(id: attrs.imageId, src: attrs.closedImgUrl, alt: "Show")
+                }
+            } // mkp
+        }
+
+    } // hideShowControl
+
+} // end class
Index: branches/features/taskProcedureRework/grails-app/taglib/WebAlbumTagLib.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/taglib/WebAlbumTagLib.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/taglib/WebAlbumTagLib.groovy	(revision 753)
@@ -0,0 +1,88 @@
+class WebAlbumTagLib {
+
+    static namespace = "wa"
+
+    def pictureAnchor = { attrs, body ->
+        def picture = attrs.remove('picture')
+        def size = attrs.remove('size')
+        out << "<a href=\"${createPictureLink(picture.id, size).encodeAsHTML()}\""
+        attrs.each { key, value ->
+            out << " $key=\"$value\""
+        }
+        out << '>'
+        out << body()
+        out << '</a>'
+    }
+
+    def pictureImg = { attrs ->
+        def picture = attrs.remove('picture')
+        def size = attrs.remove('size')
+        out << createPictureImage(picture, size, attrs)
+    }
+
+    def pictureLightboxAnchor = { attrs ->
+        def picture = attrs.remove('picture')
+        def size = attrs.remove('size')
+        def lightboxSize = attrs.remove('lightboxSize')
+        //def caption = picture.caption
+//         if (!caption) {
+            def caption = 'Show original'
+//         }
+        caption = caption.encodeAsHTML()
+        StringBuilder sb = new StringBuilder(40)
+        sb.append("<a href=\"${createPictureLink(picture.id, Image.Original).encodeAsHTML()}\"")
+        attrs.each { key, value ->
+            sb.append(" $key=\"$value\"")
+        }
+        sb.append('>')
+        sb.append(caption.replaceAll(/'/, '&#39;'))
+        sb.append('</a>')
+        def link = sb.toString().encodeAsHTML()
+        out << "<a href=\"${createPictureLink(picture.id, lightboxSize).encodeAsHTML()}\" rel=\"lightbox[list]\" title=\"${link}\">"
+        out << createPictureImage(picture, size, null)
+        out << '</a>'
+    }
+
+    private def createPictureImage(picture, size, attrs) {
+        Integer width = 0
+        Integer height = 0
+        switch (size) {
+            case Image.Original:
+                width = picture.width
+                height = picture.height
+                break
+            default:
+                width = Image.Widths[size]
+                height = Image.Widths[size]
+                break
+        }
+//         def caption = picture.caption
+//         if (!caption) {
+            def caption = 'Show original'
+//         }
+        def alt = attrs?.remove('alt')
+        if (!alt) {
+            alt = caption
+        }
+        alt = alt.encodeAsHTML()
+        def title = attrs?.remove('title')
+        if (!title) {
+            title = caption
+        }
+        title = title.encodeAsHTML()
+        StringBuilder sb = new StringBuilder(40)
+        sb.append("<img src=\"${createPictureLink(picture.id, size).encodeAsHTML()}\" alt=\"$alt\" title=\"$title\" width=\"$width\" height=\"$height\"")
+        if (attrs) {
+            attrs.each { key, value ->
+                sb.append(" $key=\"$value\"")
+            }
+        }
+        sb.append(' />')
+        sb.toString()
+    }
+
+    private def createPictureLink(id, size) {
+        def params = [ size: size, filename: Image.filename(id, size) ]
+        createLink(url: [ controller: 'pictureDetailed', action: 'view', id: id, params: params ])
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/utils/Imaging.groovy
===================================================================
--- branches/features/taskProcedureRework/grails-app/utils/Imaging.groovy	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/utils/Imaging.groovy	(revision 753)
@@ -0,0 +1,149 @@
+import java.awt.AlphaComposite
+import java.awt.Color
+import java.awt.Graphics2D
+import java.awt.geom.AffineTransform
+import java.awt.geom.Rectangle2D
+import java.awt.image.AffineTransformOp
+import java.awt.image.BufferedImage
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import javax.imageio.ImageIO
+
+class Imaging {
+
+    static def createAll(InventoryItem inventoryItem, Picture picture, InputStream stream) {
+        BufferedImage original = ImageIO.read(stream)
+        picture.contentType = 'image/jpeg'
+        picture.width = original.width
+        picture.height = original.height
+        def images = [ 
+            new Image(inventoryItem: inventoryItem, picture: picture, size: Image.Original),
+            new Image(inventoryItem: inventoryItem, picture: picture, size: Image.Large),
+            new Image(inventoryItem: inventoryItem, picture: picture, size: Image.Medium),
+            new Image(inventoryItem: inventoryItem, picture: picture, size: Image.Small)
+            ]
+        ByteArrayOutputStream output = new ByteArrayOutputStream(1024 * 1024)
+        updateImages(images, original, output)
+        images
+    }
+    
+    static def updateAll(Picture picture) {
+        def operation = picture.operation
+        if (operation == Picture.NoOp) {
+            return null
+        }
+        def images = picture.images.toArray() // Image.findAllByPicture(picture, [ sort: 'size', order: 'asc' ])
+        BufferedImage original = ImageIO.read(new ByteArrayInputStream(images[0].data))
+        AffineTransform transform = new AffineTransform();
+        def op = null
+        boolean paint = false
+        Integer width = original.width
+        Integer height = original.height
+        switch (operation) {
+            case Picture.RotateClockWise90:
+                transform.rotate(Math.PI / 2.0)
+                transform.translate(0, -height)
+                op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
+                width = original.height
+                height = original.width
+                paint = true
+                break
+            case Picture.RotateAntiClockWise90:
+                transform.rotate(-Math.PI / 2.0)
+                transform.translate(-width, 0)
+                op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
+                width = original.height
+                height = original.width
+                paint = true
+                break
+            case Picture.Rotate180:
+                transform.rotate(Math.PI)
+                transform.translate(-width, -height)
+                op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
+                break
+            case Picture.Flip: // vertical
+                transform.scale(-1.0d, 1.0d)
+                transform.translate(-width, 0)
+                op = new AffineTransformOp(transform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR)
+                break
+            case Picture.Flop: // horizontal
+                transform.scale(1.0d, -1.0d)
+                transform.translate(0, -height)
+                op = new AffineTransformOp(transform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR)
+                break
+            default:
+                return images
+                break
+        }
+        BufferedImage modified = op.filter(original, null);
+        if (paint) {
+            BufferedImage changed = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
+            Graphics2D graphics = changed.createGraphics()
+            graphics.drawImage(modified, 0, 0, width, height, null)
+            graphics.dispose()
+            modified = changed
+            picture.width = width
+            picture.height = height
+        }
+        ByteArrayOutputStream output = new ByteArrayOutputStream(1024 * 1024)
+        updateImages(images, modified, output)
+        images
+    }
+
+    private static def updateImages(images, original, stream) {
+        updateImage(images[0], original, 'jpeg', stream)
+        def large = resizeImage(original, dimensions(Image.Large), false)
+        updateImage(images[1], large, 'png', stream)
+        updateImage(images[2], resizeImage(large, dimensions(Image.Medium), true), 'png', stream)
+        updateImage(images[3], resizeImage(large, dimensions(Image.Small), true), 'png', stream)
+    }
+
+    private static def updateImage(image, data, format, stream) {
+        image.contentType = "image/${format}"
+        image.width = data.width
+        image.height = data.height
+        stream.reset()
+        if (!ImageIO.write(data, format, stream)) {
+            throw new IOException("Can't write the image in the given format '${format}'")
+        }
+        image.data = stream.toByteArray()
+    }
+
+    private static def dimensions(size) {
+        [ Image.Widths[size], Image.Heights[size] ]
+    }    
+
+    private static def resizeImage(imageBuffer, dims, fit) {
+        Integer width = dims[0]
+        Integer height = dims[1]
+        Integer imageWidth = imageBuffer.width
+        Integer imageHeight = imageBuffer.height
+      
+        Double widthScale = (double)width / (double)imageWidth
+        Double heightScale = (double)height / (double)imageHeight
+        BufferedImage resizedImage = imageBuffer
+        if (widthScale < 1.0d || heightScale < 1.0d) {
+            Double scale = Math.min(widthScale, heightScale)
+            def transform = new AffineTransform()
+            transform.scale(scale, scale)
+            def op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR)
+            resizedImage = op.filter(imageBuffer, null)
+            imageWidth = resizedImage.width
+            imageHeight = resizedImage.height
+        }
+
+        if (fit && (imageWidth < width || imageHeight < height)) {
+            BufferedImage fittedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
+            Integer left = (width - imageWidth) / 2
+            Integer top = (height - imageHeight) / 2
+            Graphics2D graphics = fittedImage.createGraphics()
+            graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f))
+            graphics.fill(new Rectangle2D.Double(0, 0, width, height))
+            graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f))
+            graphics.drawImage(resizedImage, left, top, imageWidth, imageHeight, null)
+            graphics.dispose()
+            return fittedImage
+        }
+        resizedImage
+    }
+}
Index: branches/features/taskProcedureRework/grails-app/views/_about.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/_about.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/_about.gsp	(revision 753)
@@ -0,0 +1,200 @@
+<br />
+<br />
+<div class="dialog">
+    <table>
+        <tbody>
+            <tr><td>
+                ${applicationString.encodeAsHTML()} provides a powerful but simple to use
+                Maintenance and Inventory Management Solution for your Assets.
+                Also known as a computerised maintenance management system or CMMS.
+                Initially designed with an engineering department and mid-size industrial production enviroment in mind.
+                <br />
+                <br />
+                GnuMims is a world wide community project run from 
+                <a href="http://www.gnumims.org">http://www.gnumims.org</a>
+                and released under the <a href="http://www.gnu.org/licenses/agpl.html">GNU AGPL</a> open source license.
+                <br />
+                <br />
+                The GNU AGPL requires you to make the source code available to your network users.<br />
+                So how do you do this?<br />
+                Easy, if you are running an un-modified version just leave the link to www.gnumims.org 
+                on the header image intact. This will allow your users to find the community site and 
+                with it the source code. If you are running a modified version you are welcome to 
+                use our source code repository, ask us about a custom branch or your changes
+                may be included in the main trunk. If you don't want to do either of those then 
+                create a link in your modified version to your modified source, either way you are required 
+                to make the source code available to your network users. 
+            </td></tr>
+        </tbody>
+    </table>
+</div>
+<br />
+<br />
+<div class="dialog">
+    <table>
+        <tbody>
+            <tr><td>
+            GnuMims - A web application providing a Maintenance and Inventory Management Solution for your Assets.<br />
+            Copyright (C) 2008-2010 <a href="http://www.gnumims.org/trac/wiki/GnuMimsTeam">
+                                                            Gavin Kromhout
+                                                        </a><br />
+            Copyright (C) 2008-2010 <a href="http://www.gnumims.org/trac/wiki/GnuMimsTeam">
+                                                            Steven Tucker
+                                                        </a><br />
+            Copyright (C) 2008-2010 <a href="http://www.gnumims.org/trac/wiki/GnuMimsTeam">
+                                                            Raymond Smith
+                                                        </a><br />
+            <br />
+            This program is free software: you can redistribute it and/or modify<br />
+            it under the terms of the GNU Affero General Public License as published by<br />
+            the Free Software Foundation, either version 3 of the License, or<br />
+            (at your option) any later version.<br />
+            <br />
+            This program is distributed in the hope that it will be useful,<br />
+            but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
+            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br />
+            GNU Affero General Public License for more details.<br />
+            <br />
+            You should have received a copy of the GNU Affero General Public License<br />
+            along with this program.  If not, see <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>
+            </td></tr>
+        </tbody>
+    </table>
+</div>
+<br />
+<br />
+<div class="dialog">
+    <table>
+        <tbody>
+            <tr class="prop">
+                <td valign="top" class="name">
+                    Silk icon set acknowledgement.<br />
+                    Many thanks for the fabulous silk icon set.
+                </td>
+            </tr>
+
+            <tr class="prop">
+                <td valign="top" class="name">Author:</td>
+
+                <td valign="top" class="value">
+                    Mark James - <a href="http://www.famfamfam.com/lab/icons/silk/">http://www.famfamfam.com/lab/icons/silk/</a>
+                </td>
+
+            </tr>
+
+            <tr class="prop">
+                <td valign="top" class="name">License:</td>
+
+                <td valign="top" class="value">
+                    <a href="http://creativecommons.org/licenses/by/3.0/">http://creativecommons.org/licenses/by/3.0/</a>
+                </td>
+
+            </tr>
+
+        </tbody>
+    </table>
+</div>
+<br />
+<br />
+<div class="dialog">
+    <table>
+        <tbody>
+            <tr class="prop">
+                <td valign="top" class="name">
+                    Lightbox acknowledgement.<br />
+                    Many thanks for Lightbox.<br />
+                    Used to display inventory item pictures.
+                </td>
+
+            </tr>
+
+            <tr class="prop">
+                <td valign="top" class="name">Author:</td>
+
+                <td valign="top" class="value">
+                    Lokesh Dhakar - <a href="http://www.lokeshdhakar.com/projects/lightbox2/">http://www.lokeshdhakar.com/projects/lightbox2/</a>
+                </td>
+
+            </tr>
+
+            <tr class="prop">
+                <td valign="top" class="name">License:</td>
+
+                <td valign="top" class="value">
+                    <a href="http://creativecommons.org/licenses/by/2.5/">http://creativecommons.org/licenses/by/2.5/</a>
+                </td>
+
+            </tr>
+
+        </tbody>
+    </table>
+</div>
+<br />
+<br />
+<div class="dialog">
+    <table>
+        <tbody>
+            <tr class="prop">
+                <td valign="top" class="name">
+                    WebAlbum acknowledgement.<br />
+                    Many thanks for the inspiration and code.<br />
+                    Used to display inventory item pictures.
+                </td>
+
+            </tr>
+
+            <tr class="prop">
+                <td valign="top" class="name">Author:</td>
+
+                <td valign="top" class="value">
+                    John Leach - <a href="http://www.syger.it/Tutorials/GrailsWebAlbum.html">http://www.syger.it/Tutorials/GrailsWebAlbum.html</a>
+                </td>
+
+            </tr>
+
+            <tr class="prop">
+                <td valign="top" class="name">License:</td>
+
+                <td valign="top" class="value">
+                    <a href="http://www.apache.org/licenses/LICENSE-2.0.html">http://www.apache.org/licenses/LICENSE-2.0.html</a>
+                </td>
+
+            </tr>
+
+        </tbody>
+    </table>
+</div>
+<br />
+<br />
+<div class="dialog">
+    <table>
+        <tbody>
+            <tr><td>
+                The MySQL java connector (if included) is licensed under the GNU GPL V02.<br />
+                Sun Microsystem's JDBC Driver for MySQL.<br />
+                Copyright 2003-2008 MySQL AB, 2008 Sun Microsystems.<br />
+                and can be obtained from <a href="http://dev.mysql.com/downloads/connector/j/5.0.html">http://dev.mysql.com/downloads/connector/j/5.0.html</a>
+            </td></tr>
+        </tbody>
+    </table>
+</div>
+<br />
+<br />
+<div class="dialog">
+    <table>
+        <tbody>
+            <tr>
+                <td>
+                The Grails-${grailsVersion.encodeAsHTML()} web framework and the plugins used are available under 
+                the <a href="http://www.apache.org/licenses/LICENSE-2.0.html">Apache 2.0</a>
+                license from  <a href="http://www.grails.org">http://www.grails.org</a>
+                </td>
+            </tr>
+                <tr>
+                    <td>
+                        Plugins: ${plugins}
+                    </td>
+                </tr>
+        </tbody>
+    </table>
+</div>
Index: branches/features/taskProcedureRework/grails-app/views/addressDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/addressDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/addressDetailed/create.gsp	(revision 753)
@@ -0,0 +1,139 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Address</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Address</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${addressInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${addressInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            
+                            <g:if test="${addressInstance.supplier}">
+                                <g:hiddenField name="supplier.id" value="${addressInstance.supplier.id}"/>
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="supplier">Supplier:</label>
+                                    </td>
+                                    <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'supplier','errors')}">
+                                        <g:link controller="supplierDetailed" action="show" id="${addressInstance.supplier.id}">
+                                            ${addressInstance.supplier.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr>
+                            </g:if>
+                            
+                            <g:if test="${addressInstance.person}">
+                                <g:hiddenField name="person.id" value="${addressInstance.person.id}"/>
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="person">Person:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link controller="person" action="show" id="${addressInstance.person.id}">
+                                            ${addressInstance.person.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr> 
+                            </g:if>
+                            
+                            <g:if test="${addressInstance.site}">
+                                <g:hiddenField name="site.id" value="${addressInstance.site.id}"/>
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="site">Site:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link controller="siteDetailed" action="show" id="${addressInstance.site.id}">
+                                            ${addressInstance.site.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr> 
+                            </g:if>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="addressType">Address Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'addressType','errors')}">
+                                    <g:select optionKey="id" from="${AddressType.list()}" name="addressType.id" value="${addressInstance?.addressType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="street1">Street 1:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'street1','errors')}">
+                                    <input type="text" maxlength="50" id="street1" name="street1" value="${fieldValue(bean:addressInstance,field:'street1')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="street2">Street 2:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'street2','errors')}">
+                                    <input type="text" maxlength="50" id="street2" name="street2" value="${fieldValue(bean:addressInstance,field:'street2')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="city">City:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'city','errors')}">
+                                    <input type="text" maxlength="50" id="city" name="city" value="${fieldValue(bean:addressInstance,field:'city')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="state">State:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'state','errors')}">
+                                    <input type="text" maxlength="50" id="state" name="state" value="${fieldValue(bean:addressInstance,field:'state')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="postCode">Post Code:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'postCode','errors')}">
+                                    <input type="text" maxlength="50" id="postCode" name="postCode" value="${fieldValue(bean:addressInstance,field:'postCode')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="country">Country:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'country','errors')}">
+                                    <input type="text" maxlength="50" id="country" name="country" value="${fieldValue(bean:addressInstance,field:'country')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/addressDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/addressDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/addressDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,140 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit Address</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Address</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${addressInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${addressInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${addressInstance?.id}" />
+                <input type="hidden" name="version" value="${addressInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            
+                            <g:if test="${addressInstance.supplier}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="supplier">Supplier:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link controller="supplierDetailed" action="show" id="${addressInstance.supplier.id}">
+                                            ${addressInstance.supplier.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr> 
+                            </g:if>
+                            
+                            <g:if test="${addressInstance.person}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="person">Person:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link controller="person" action="show" id="${addressInstance.person.id}">
+                                            ${addressInstance.person.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr> 
+                            </g:if>
+                            
+                            <g:if test="${addressInstance.site}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="site">Site:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link controller="siteDetailed" action="show" id="${addressInstance.site.id}">
+                                            ${addressInstance.site.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr> 
+                            </g:if>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="addressType">Address Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'addressType','errors')}">
+                                    <g:select optionKey="id" from="${AddressType.list()}" name="addressType.id" value="${addressInstance?.addressType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="street1">Street1:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'street1','errors')}">
+                                    <input type="text" maxlength="50" id="street1" name="street1" value="${fieldValue(bean:addressInstance,field:'street1')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="street2">Street2:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'street2','errors')}">
+                                    <input type="text" maxlength="50" id="street2" name="street2" value="${fieldValue(bean:addressInstance,field:'street2')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="city">City:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'city','errors')}">
+                                    <input type="text" maxlength="50" id="city" name="city" value="${fieldValue(bean:addressInstance,field:'city')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="state">State:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'state','errors')}">
+                                    <input type="text" maxlength="50" id="state" name="state" value="${fieldValue(bean:addressInstance,field:'state')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="postCode">Post Code:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'postCode','errors')}">
+                                    <input type="text" maxlength="50" id="postCode" name="postCode" value="${fieldValue(bean:addressInstance,field:'postCode')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="country">Country:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:addressInstance,field:'country','errors')}">
+                                    <input type="text" maxlength="50" id="country" name="country" value="${fieldValue(bean:addressInstance,field:'country')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/addressDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/addressDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/addressDetailed/list.gsp	(revision 753)
@@ -0,0 +1,80 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Address List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Address List</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="street1" title="Street1" />
+                        
+                   	        <g:sortableColumn property="street2" title="Street2" />
+                        
+                   	        <g:sortableColumn property="city" title="City" />
+                        
+                   	        <g:sortableColumn property="state" title="State" />
+                        
+                   	        <g:sortableColumn property="postCode" title="Post Code" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${addressInstanceList}" status="i" var="addressInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/addressDetailed/show/${addressInstance.id}"'>
+                                ${fieldValue(bean:addressInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/addressDetailed/show/${addressInstance.id}"'>
+                                ${fieldValue(bean:addressInstance, field:'street1')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/addressDetailed/show/${addressInstance.id}"'>
+                                ${fieldValue(bean:addressInstance, field:'street2')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/addressDetailed/show/${addressInstance.id}"'>
+                                ${fieldValue(bean:addressInstance, field:'city')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/addressDetailed/show/${addressInstance.id}"'>
+                                ${fieldValue(bean:addressInstance, field:'state')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/addressDetailed/show/${addressInstance.id}"'>
+                                ${fieldValue(bean:addressInstance, field:'postCode')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${addressInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${addressInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/addressDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/addressDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/addressDetailed/show.gsp	(revision 753)
@@ -0,0 +1,115 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show Address</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Address</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:addressInstance, field:'id')}</td>
+                            
+                        </tr>
+                            
+                            <g:if test="${addressInstance.supplier}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">Supplier:</td>
+                                    
+                                    <td valign="top" class="value"><g:link controller="supplierDetailed" action="show" id="${addressInstance.supplier.id}">${addressInstance.supplier.encodeAsHTML()}</g:link></td>
+                                    
+                                </tr>
+                            </g:if>
+                            
+                            <g:if test="${addressInstance.person}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">Person:</td>
+                                    
+                                    <td valign="top" class="value"><g:link controller="person" action="show" id="${addressInstance.person.id}">${addressInstance.person.encodeAsHTML()}</g:link></td>
+                                    
+                                </tr>
+                            </g:if>
+                            
+                            <g:if test="${addressInstance.site}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">Site:</td>
+                                    
+                                    <td valign="top" class="value"><g:link controller="siteDetailed" action="show" id="${addressInstance.site.id}">${addressInstance.site.encodeAsHTML()}</g:link></td>
+                                    
+                                </tr>
+                            </g:if>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Address Type:</td>
+                            
+                            <td valign="top" class="value">${addressInstance?.addressType?.encodeAsHTML()}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Street1:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:addressInstance, field:'street1')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Street2:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:addressInstance, field:'street2')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">City:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:addressInstance, field:'city')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">State:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:addressInstance, field:'state')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Post Code:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:addressInstance, field:'postCode')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Country:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:addressInstance, field:'country')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${addressInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/appConfig/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/appConfig/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/appConfig/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create AppConfig</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">AppConfig List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create AppConfig</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${appConfigInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${appConfigInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:appConfigInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="100" id="name" name="name" value="${fieldValue(bean:appConfigInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="value">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:appConfigInstance,field:'value','errors')}">
+                                    <textarea rows="5" cols="40" name="value">${fieldValue(bean:appConfigInstance, field:'value')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:appConfigInstance,field:'description','errors')}">
+                                    <textarea rows="5" cols="40" name="description">${fieldValue(bean:appConfigInstance, field:'description')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/appConfig/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/appConfig/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/appConfig/edit.gsp	(revision 753)
@@ -0,0 +1,68 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit AppConfig</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">AppConfig List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New AppConfig</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit AppConfig</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${appConfigInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${appConfigInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${appConfigInstance?.id}" />
+                <input type="hidden" name="version" value="${appConfigInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:appConfigInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="100" id="name" name="name" value="${fieldValue(bean:appConfigInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="value">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:appConfigInstance,field:'value','errors')}">
+                                    <textarea rows="5" cols="40" name="value">${fieldValue(bean:appConfigInstance, field:'value')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:appConfigInstance,field:'description','errors')}">
+                                    <textarea rows="5" cols="40" name="description">${fieldValue(bean:appConfigInstance, field:'description')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/appConfig/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/appConfig/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/appConfig/list.gsp	(revision 753)
@@ -0,0 +1,55 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>AppConfig List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New AppConfig</g:link></span>
+        </div>
+        <div class="body">
+            <h1>AppConfig List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="value" title="Value" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${appConfigInstanceList}" status="i" var="appConfigInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${appConfigInstance.id}">${fieldValue(bean:appConfigInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:appConfigInstance, field:'name')}</td>
+                        
+                            <td>${fieldValue(bean:appConfigInstance, field:'value')}</td>
+                        
+                            <td>${fieldValue(bean:appConfigInstance, field:'description')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${appConfigInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/appConfig/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/appConfig/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/appConfig/show.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show AppConfig</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">AppConfig List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New AppConfig</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show AppConfig</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:appConfigInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:appConfigInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Value:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:appConfigInstance, field:'value')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:appConfigInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${appConfigInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/appCore/appAdmin.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/appCore/appAdmin.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/appCore/appAdmin.gsp	(revision 753)
@@ -0,0 +1,95 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Admin</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label>Create:</label>
+                            </td>
+                            <td valign="top" class="value">
+
+                                <g:if test="${offerBaseDataCreation}">
+                                    <g:link action="createBaseData">Base</g:link> - Create the base data required for the application to function.
+                                </g:if>
+                                <g:else>
+                                    <g:if test="${baseDataCreated}">
+                                        Base data has been created.
+                                    </g:if>
+                                </g:else>
+
+                                <br />
+
+                                <g:if test="${demoDataCreationDisabled}">
+                                    Demo data creation has been disabled.
+                                </g:if>
+                                <g:else>
+                                    <g:if test="${offerDemoDataCreation}">
+                                        <g:link action="createDemoData">Demo</g:link> - Create demo data for some example sites.
+                                        <br />
+                                        <g:link action="disableDemoDataCreation">Disable</g:link> - Disable demo data creation.
+                                    </g:if>
+                                    <g:else>
+                                        <g:if test="${demoDataCreated}">
+                                            Demo data has been created.
+                                        </g:if>
+                                    </g:else>
+                                </g:else>
+
+                                <br />
+                                <br />
+
+                                <g:link action="createRecommendedAssetExtendedAttributes">Asset Extended Attributes</g:link> - Create recommended extended attributes for assets.
+                                <br />
+                                <g:link action="createRecommendedAssetSubItemExtendedAttributes">Sub Asset Extended Attributes</g:link> - Create recommended extended attributes for level 1 sub assets.
+
+                            </td>
+                        </tr>
+
+                        <g:if env="development">
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Bulk Test:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:link action="createBulkTestData">All Types</g:link> - Create a large volume of test data.
+                                    <br />
+                                    <g:link action="createBulkInventoryTestData">Inventory</g:link> - Create a large volume of inventory test data.
+                                </td>
+                            </tr>
+                        </g:if>
+
+                    </tbody>
+                </table>
+            </div> <!--End dialog-->
+            <br />
+            <br />
+            <div class="errors">
+                Warning!<br />
+                The pages bellow this line are for use by the application admin only and NOT for daily use.<br />
+                They allow direct administration of the back-end data, uncontrolled cascade deletion and updates may occur.<br />
+                The manager authorisation and pages should be used for normal daily use.<br />
+            </div>
+            <br/>
+            <div class="dialog">
+                <ul>
+                <g:each var="c" in="${grailsApplication.controllerClasses.sort { p1, p2 -> p1.fullName.compareToIgnoreCase(p2.fullName) } }">
+                        <li class="controller"><g:link controller="${c.logicalPropertyName}">${c.logicalPropertyName[0].toUpperCase() + c.logicalPropertyName[1..-1]}</g:link></li>
+                </g:each>
+                </ul>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/appCore/appLog.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/appCore/appLog.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/appCore/appLog.gsp	(revision 753)
@@ -0,0 +1,20 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Application Log</title>
+        <nav:resources override="true"/>
+    </head>
+    <body onload="textAreaScrollBottom('log');">
+        <div class="nav">
+            <h1>Application Log</h1>
+        </div>
+        <div class="body">
+
+            <textarea rows="30" cols="90" id="log" name="log" readonly="yes">
+                ${log.encodeAsHTML()}
+            </textarea>
+
+        </div> <!--End body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/appCore/changePassword.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/appCore/changePassword.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/appCore/changePassword.gsp	(revision 753)
@@ -0,0 +1,52 @@
+<head>
+    <meta name="layout" content="main" />
+    <title>Change Password</title>
+    <nav:resources override="true"/>
+</head>
+
+<body onload="document.changePasswordForm.pass.focus();">
+    <div class="nav">
+        <nav:renderSubItems group="nav"/>
+    </div>
+
+    <div class="body">
+        <g:if test="${flash.message}">
+        <div class="message">${flash.message}</div>
+        </g:if>
+        <g:hasErrors bean="${personInstance}">
+        <div class="errors">
+            <g:renderErrors bean="${personInstance}" as="list" />
+        </div>
+        </g:hasErrors>
+
+            <g:form name="changePasswordForm" id="changePasswordForm">
+                <div class="dialog">
+                    <table>
+                        <tbody>
+
+                        <tr class="prop">
+                            <td valign="top" class="name"><label for="pass">Password:</label></td>
+                            <td valign="top" class="value ${hasErrors(bean:personInstance,field:'pass','errors')}">
+                                <input type="password" id="pass" name="pass" />
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name"><label for="confirmPass">Confirm password:</label></td>
+                            <td valign="top" class="value">
+                                <input type="password" id="confirmPass" name="confirmPass" />
+                            </td>
+                        </tr>
+
+                    </tbody>
+                </table>
+            </div>
+
+            <div class="buttons">
+                <span class="button"><g:actionSubmit class="save" value="Change Password" action="changePassword"/></span>
+            </div>
+        </g:form>
+
+    </div>
+
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/appCore/changeSessionTimeout.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/appCore/changeSessionTimeout.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/appCore/changeSessionTimeout.gsp	(revision 753)
@@ -0,0 +1,49 @@
+<head>
+	<meta name="layout" content="main" />
+	<title>Change Session Timeout</title>
+    <nav:resources override="true"/>
+</head>
+
+<body onload="document.changeSessionTimeoutForm.sessionTimeout.focus();">        
+    <div class="nav">
+        <nav:renderSubItems group="nav"/>
+    </div>
+
+	<div class="body">
+		<g:if test="${flash.message}">
+		<div class="message">${flash.message}</div>
+		</g:if>
+		<g:hasErrors bean="${personInstance}">
+		<div class="errors">
+			<g:renderErrors bean="${personInstance}" as="list" />
+		</div>
+		</g:hasErrors>
+
+		<g:form name="changeSessionTimeoutForm" id="changeSessionTimeout">
+			<div class="dialog">
+				<table>
+				<tbody>
+
+					<tr class="prop">
+						<td valign="top" class="name">
+                            <label for="sessionTimeout">Session timeout:</label>
+                        </td>
+
+                        <td valign="top" class="value">
+						<input valign="top" class="duration ${hasErrors(bean:personInstance,field:'sessionTimeout','errors')}"
+                             type="text" id="sessionTimeout" name="sessionTimeout" value="${fieldValue(bean:personInstance,field:'sessionTimeout')}"/>
+                            seconds
+					</tr>
+
+				</tbody>
+				</table>
+			</div>
+
+			<div class="buttons">
+				<span class="button"><g:actionSubmit class="save" value="Save" action="changeSessionTimeout"/></span>
+			</div>
+		</g:form>
+
+	</div>
+
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/appCore/manager.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/appCore/manager.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/appCore/manager.gsp	(revision 753)
@@ -0,0 +1,93 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Manager</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+                <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label>Manage:</label>
+                            </td>
+                            <td valign="top" class="value">
+                                <a href="${createLink(controller:'person', action:'list')}">Application users</a>
+                                <br />
+                                <a href="${createLink(controller:'personGroupDetailed', action:'list')}">Assigned Groups</a>
+                                <br />
+                                <a href="${createLink(controller:'costCodeDetailed', action:'list')}">Cost Codes</a>
+                                <br />
+                                <a href="${createLink(controller:'departmentDetailed', action:'list')}">Departments</a>
+                                <br />
+                                <a href="${createLink(controller:'inventoryLocationDetailed', action:'list')}">Inventory Locations</a>
+                                <br />
+                                <a href="${createLink(controller:'inventoryGroupDetailed', action:'list')}">Inventory Groups</a>
+                                <br />
+                                <a href="${createLink(controller:'inventoryStoreDetailed', action:'list')}">Inventory Stores</a>
+                                <br />
+                                <a href="${createLink(controller:'maintenancePolicyDetailed', action:'list')}">Maintenance Policies</a>
+                                <br />
+                                <a href="${createLink(controller:'purchasingGroupDetailed', action:'list')}">Purchasing Groups</a>
+                                <br />
+                                <a href="${createLink(controller:'productionReferenceDetailed', action:'list')}">Production Reference</a>
+                                <br />
+                                <a href="${createLink(controller:'supplierDetailed', action:'list')}">Suppliers</a>
+                                <br />
+                                <a href="${createLink(controller:'taskGroupDetailed', action:'list')}">Task Groups</a>
+                                <br />
+                                <a href="${createLink(controller:'taskProcedureDetailed', action:'list')}">Task Procedures</a>
+                                <br />
+                                <a href="${createLink(controller:'taskRecurringScheduleDetailed', action:'list')}">Task Recurring Schedules</a>
+                                <br />
+                                <a href="${createLink(controller:'unitOfMeasureDetailed', action:'list')}">Unit Of Measure</a>
+                                <br />
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label>Application:</label>
+                            </td>
+                            <td valign="top" class="value">
+                                <g:link action="appLog">
+                                    View
+                                </g:link> - The application log file.
+                                <br />
+                                <g:link action="rebuildTextSearchIndex">
+                                    Rebuild
+                                </g:link> - Rebuild the text search index.
+                                <br />
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label>Entity Relationship Diagram:</label>
+                            </td>
+                            <td valign="top" class="value">
+
+                                <a href="${createLink(controller:'classDiagram', action:'model', params:[outputFormat: 'pdf', skin: 'classicSpaced', showMethods: 'false', autoUpdate: 'false'])}">PDF</a>
+                                <br />
+                                <a href="${createLink(controller:'classDiagram', action:'legend', target:'_blank')}">Legend</a>
+                                <br />
+                                <a href="${createLink(controller:'classDiagram', action:'show')}">Interactive.</a>
+                            </td>
+                        </tr>
+
+                    </tbody>
+                </table>
+            </div> <!--End dialog-->
+        </div> <!--End body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/appCore/start.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/appCore/start.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/appCore/start.gsp	(revision 753)
@@ -0,0 +1,278 @@
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+    <meta name="layout" content="main" />
+    <title>Start</title>
+    <nav:resources override="true"/>
+    <resource:tabView skin="tabviewCustom" />
+    <resource:dateChooser />
+</head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${appCore}">
+                <div class="errors">
+                    <g:renderErrors bean="${appCore}" as="list" />
+                </div>
+            </g:hasErrors>
+
+            <richui:tabView id="tabView">
+
+                <richui:tabLabels>
+                    <richui:tabLabel selected="${showTab.quickLinks}" title="Quick Links" />
+                    <richui:tabLabel selected="${showTab.reports}" title="Reports" />
+                    <richui:tabLabel selected="${showTab.Options}" title="Options" />
+                    <richui:tabLabel selected="${showTab.about}" title="About" />
+                </richui:tabLabels>
+
+                <richui:tabContents>
+
+<!-- Tasks tab -->
+                    <richui:tabContent>
+                        <br />
+                        <br />
+                        <div class="dialog">
+                            <table>
+                                <tbody>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">
+                                            <label>My Tasks:</label>
+                                        </td>
+                                        <td valign="top" class="value">
+                                            <g:link controller="taskDetailed"
+                                                            action="search"
+                                                            params="[quickSearch: 'myTodays']">
+                                                            Today
+                                            </g:link>
+                                        </td>
+                                    </tr>
+            
+                                    <tr class="prop">
+                                        <td valign="top" class="name">
+                                            <label>All Tasks:</label>
+                                        </td>
+                                        <td valign="top" class="value">
+                                            <g:link controller="taskDetailed" 
+                                                            action="search"
+                                                            params="[quickSearch: 'pastWeek']">
+                                                            Past Week
+                                            </g:link>
+                                            <br />
+                                            <g:link controller="taskDetailed" 
+                                                            action="searchCalendar"
+                                                            params="[quickSearch: 'searchPlannersRange']">
+                                                            Calendar
+                                            </g:link>
+                                        </td>
+                                    </tr>
+
+<!--                                    More Quick Links:
+                                    Open Tasks
+                                    Closed Tasks
+                                    Tasks I lead.
+                                    Week calender
+                                    Recent
+                                    Today's Entries
+                                    My Entries.
+                                    Date ranges-->
+
+                                </tbody>
+                            </table>
+                        </div> <!--End dialog-->
+                    </richui:tabContent>
+<!-- End Tasks tab -->
+
+<!-- Reports tab -->
+                    <richui:tabContent>
+                        <br />
+                        <br />
+                        <div class="dialog">
+                            <table>
+                                <tbody>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">
+                                            <label>Frequently Used:</label>
+                                        </td>
+                                        <td valign="top" class="value">
+                                            <g:jasperReport controller="report"
+                                                                            action="reactiveRatio"
+                                                                            jasper="reactiveRatio"
+                                                                            name="Reactive Ratio"
+                                                                            format="PDF, XLS">
+                                                <richui:dateChooser name="startDate" id="reactiveRatio_startDate" format="dd-MM-yyyy" value="${new Date()-7}" />
+                                                to
+                                                <richui:dateChooser name="endDate" id="reactiveRatio_endDate" format="dd-MM-yyyy" value="${new Date()}" />
+                                            </g:jasperReport>
+                                            <br />
+                                            <g:jasperReport controller="report"
+                                                                            action="immediateCallouts"
+                                                                            jasper="immediateCallouts"
+                                                                            name="Immediate Callouts"
+                                                                            format="PDF, XLS">
+                                                <richui:dateChooser name="startDate" id="immediateCallouts_startDate" format="dd-MM-yyyy" value="${new Date()-7}" />
+                                                to
+                                                <richui:dateChooser name="endDate" id="immediateCallouts_endDate" format="dd-MM-yyyy" value="${new Date()}" />
+                                            </g:jasperReport>
+                                            <br />
+                                            <g:jasperReport controller="report"
+                                                                            action="stockTakeOverview"
+                                                                            jasper="stockTakeOverview"
+                                                                            name="Stock Take (Overview)"
+                                                                            format="PDF, XLS">
+                                                <g:helpBalloon class="helpballoon" code="report.stock.take.overview" />
+                                            </g:jasperReport>
+                                            <br />
+                                            <g:jasperReport controller="report"
+                                                                            action="stockTakeByLocation"
+                                                                            jasper="stockTakeByLocation"
+                                                                            name="Stock Take (By Location)"
+                                                                            format="PDF, XLS">
+                                                <g:textField name="locationString" value="e.g: A1%, C55" />
+                                                <g:helpBalloon class="helpballoon" code="report.stock.take.by.location" />
+                                            </g:jasperReport>
+                                            <br />
+                                            <g:jasperReport controller="report"
+                                                                            action="templatePortrait"
+                                                                            jasper="templatePortrait"
+                                                                            name="Template (Portrait)"
+                                                                            format="PDF, XLS">
+                                                <g:link controller="report" action="downloadTemplate" params="[fileName: 'templatePortrait.jrxml']">
+                                                    Download
+                                                </g:link>
+                                            </g:jasperReport>
+                                            <br />
+                                            <g:jasperReport controller="report"
+                                                                            action="templateLandscape"
+                                                                            jasper="templateLandscape"
+                                                                            name="Template (Landscape)"
+                                                                            format="PDF, XLS">
+                                                <g:link controller="report" action="downloadTemplate" params="[fileName: 'templateLandscape.jrxml']">
+                                                    Download
+                                                </g:link>
+                                            </g:jasperReport>
+                                            <br />
+                                        </td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">
+                                            <label>Assets:</label>
+                                        </td>
+                                        <td valign="top" class="value">
+                                            <g:link controller="report" action="equipmentRegisterOhsGsp">
+                                                Equipment Register (OH&amp;S)
+                                            </g:link>
+                                            <br />
+                                            <br />
+                                            <g:link controller="report" action="regulatoryRequirementsGsp">
+                                                <img  src="${resource(dir:'images/skin',file:'script_lightning.png')}" alt="Regulatory Requirement" title="Regulatory Requirement" />
+                                                Regulatory Requirements
+                                            </g:link>
+                                            <br />
+                                            <br />
+                                            <g:link controller="report" action="mandatoryRequirementsGsp">
+                                                <img  src="${resource(dir:'images/skin',file:'script.png')}" alt="Mandatory Requirement" title="Mandatory Requirement" />
+                                                Mandatory Requirements
+                                            </g:link>
+                                            <br />
+                                            <br />
+                                            <g:jasperReport controller="report"
+                                                                            action="equipmentRegisterFinancial"
+                                                                            jasper="equipmentRegisterFinancial"
+                                                                            name="Equipment Register (Financial)"
+                                                                            format="PDF, XLS">
+                                                <g:select optionKey="id"
+                                                                    from="${sections}"
+                                                                    name="section.id">
+                                                </g:select>
+                                            </g:jasperReport>
+                                            <br />
+                                            <g:jasperReport controller="report"
+                                                                            action="assetRegister"
+                                                                            jasper="assetRegister"
+                                                                            name="Asset Register"
+                                                                            format="PDF, XLS">
+                                                <g:select optionKey="id"
+                                                                    from="${sections}"
+                                                                    name="section.id">
+                                                </g:select>
+                                            </g:jasperReport>
+                                            <br />
+                                            <g:jasperReport controller="report"
+                                                                            action="assetDetail"
+                                                                            jasper="assetDetail"
+                                                                            name="Asset Detail"
+                                                                            format="PDF, XLS">
+                                                <g:select optionKey="id"
+                                                                    from="${sections}"
+                                                                    name="section.id"
+                                                                    noSelection="['all':/${g.message(code:'default.all.select.text')}/]">
+                                                </g:select>
+                                            </g:jasperReport>
+                                            <br />
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">
+                                            <label>Inventory:</label>
+                                        </td>
+                                        <td valign="top" class="value">
+                                                <g:link controller="report" action="inventoryValueOverviewGsp">
+                                                    Total Value (Overview)
+                                                </g:link>
+                                                <br />
+                                                <br />
+                                                <g:link controller="report" action="inventoryValueDetailedGsp">
+                                                    Detailed Value
+                                                </g:link>
+                                        </td>
+                                    </tr>
+
+                                </tbody>
+                            </table>
+                        </div> <!--End dialog-->
+                    </richui:tabContent>
+<!-- End Reports tab  -->
+
+<!-- Options tab -->
+                    <richui:tabContent>
+                        <br />
+                        <br />
+                        <div class="dialog">
+                            <table>
+                                <tbody>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">
+                                            <label>Change:</label>
+                                        </td>
+                                        <td valign="top" class="value">
+                                            <a href="${createLink(action:'changePassword')}"> Password</a>
+                                            <br />
+                                            <a href="${createLink(action:'changeSessionTimeout')}">Session Timeout</a>
+                                        </td>
+                                    </tr>
+
+                                </tbody>
+                            </table>
+                        </div> <!--End dialog-->
+                    </richui:tabContent>
+<!-- End Options tab -->
+
+<!-- About tab -->
+                    <richui:tabContent>
+                        <g:render template="/about" />
+                    </richui:tabContent>
+<!-- End About tab -->
+
+                </richui:tabContents>
+            </richui:tabView>
+
+        </div> <!--End body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetDetailed/copy.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetDetailed/copy.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetDetailed/copy.gsp	(revision 753)
@@ -0,0 +1,107 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Asset Copy</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Asset Copy</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${assetInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assetInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <g:hiddenField name="assetToCopy.id" value="${assetToCopy.id}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Copying:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    ${assetToCopy.encodeAsHTML()}
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="copyMethod">Sub Items:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <p>
+                                        <input type="radio" name="copyMethod" value="link" />
+                                        Link
+                                        <g:helpBalloon class="helpballoon" code="asset.copy.method" />
+                                    </p>
+                                    <p>
+                                        <input type="radio" name="copyMethod" value="copy" />
+                                        Copy
+                                    </p>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:assetInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:assetInstance,field:'description')}"/>
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:assetInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${assetInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="section">Section:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'section','errors')}">
+                                    <g:select optionKey="id" from="${Section.list()}" name="section.id" value="${assetInstance?.section?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Create" action="saveCopy"/></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetDetailed/create.gsp	(revision 753)
@@ -0,0 +1,80 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Asset</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${assetInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assetInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:assetInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:assetInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:assetInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${assetInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="section">Section:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'section','errors')}">
+                                    <g:select optionKey="id" from="${Section.list()}" name="section.id" value="${assetInstance?.section?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,202 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit Asset</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${assetInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assetInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${assetInstance?.id}" />
+                <input type="hidden" name="version" value="${assetInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="name">Asset</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:assetInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="100" id="description" name="description" value="${fieldValue(bean:assetInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:assetInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${assetInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="section">Section:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'section','errors')}">
+                                    <g:select optionKey="id" from="${Section.list()}" name="section.id" value="${assetInstance?.section?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">Extended Attributes</td>
+                                <td  valign="top" style="text-align:left;" class="value">
+                                </td>
+                            </tr>
+                            
+                            <g:each var="a" in="${assetInstance.assetExtendedAttributes.sort { p1, p2 -> p1.extendedAttributeType.name.compareToIgnoreCase(p2.extendedAttributeType.name) }}">
+                                <tr class="prop">
+                                    <td valign="top" class="groupName">
+                                        ${a.extendedAttributeType.name.encodeAsHTML()}:
+                                    </td>
+                                    
+                                    <td  valign="top" style="text-align:left;" class="value">
+                                        <g:link controller="assetExtendedAttributeDetailed" action="edit" id="${a.id}">
+                                            ${a.value.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                
+                                </tr>
+                            </g:each>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="name"></td>
+                                <td  valign="top" style="text-align:left;" class="value">
+                                    <g:link controller="assetExtendedAttributeDetailed" params="['asset.id':assetInstance?.id]" action="create">+Add Extended Attribute</g:link>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="assetSubItems">Asset Tree</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'assetSubItems','errors')}">
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    Level 1 sub items:
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetInstance,field:'assetSubItems','errors')}">
+                                    <custom:checkBoxList name="assetSubItems"
+                                                                    from="${possibleAssetSubItems}"
+                                                                    value="${assetInstance?.assetSubItems.collect{it.id}}"
+                                                                    optionKey="id"
+                                                                    sortBy="name"
+                                                                    linkController="assetSubItemDetailed"
+                                                                    linkAction="show"/>
+
+                                </td>
+                            </tr> 
+
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">Life Plan</td>
+
+                                <td  valign="top" style="text-align:left;" class="value">
+                                </td>
+
+                            </tr>
+                            
+                            <g:each var="t" in="${parentPMs}">
+                                <tr class="prop">
+                                    <td valign="top" class="name"></td>
+                                    
+                                    <td  valign="top" style="text-align:left;" class="value">
+                                        <g:link controller="taskDetailed" action="show" id="${t.id}">
+                                            Task #${t.id}
+                                        </g:link>
+                                        <g:if test="${t.approved}" >
+                                            <img  src="${resource(dir:'images/skin',file:'cog.png')}" alt="Approved" title="Approved" />
+                                        </g:if>
+                                        <g:if test="${t.taskRecurringSchedule?.enabled}" >
+                                            <img  src="${resource(dir:'images/skin',file:'arrow_refresh.png')}" alt="Recurrence Enabled" title="Recurrence Enabled" />
+                                        </g:if>
+                                        <g:if test="${t.taskStatus.id == 2}" >
+                                            <img  src="${resource(dir:'images/skin',file:'arrow_right.png')}" alt="In Progress" title="In Progress" />
+                                        </g:if>
+                                        <g:if test="${t.attentionFlag}" >
+                                            <img  src="${resource(dir:'images/skin',file:'flag_red.png')}" alt="Attention Flag" title="Attention Flag" />
+                                        </g:if>
+                                        <g:if test="${t.taskStatus.id == 3}" >
+                                            <img  src="${resource(dir:'images/skin',file:'tick.png')}" alt="Complete" title="Complete" />
+                                        </g:if>
+                                        <br />
+                                        ${fieldValue(bean:t, field:'description')}
+                                        <br />
+                                        <g:if test="${t.safetyRequirement}" >
+                                            <img  src="${resource(dir:'images/skin',file:'lightning.png')}" alt="Safety Requirement" title="Safety Requirement" />
+                                            Safety
+                                        </g:if>
+                                        <g:if test="${t.regulatoryRequirement}" >
+                                            <img  src="${resource(dir:'images/skin',file:'script_lightning.png')}" alt="Regulatory Requirement" title="Regulatory Requirement" />
+                                            Regulatory
+                                        </g:if>
+                                        <g:if test="${t.mandatoryRequirement}" >
+                                            <img  src="${resource(dir:'images/skin',file:'script.png')}" alt="Mandatory Requirement" title="Mandatory Requirement" />
+                                            Mandatory
+                                        </g:if>
+                                    </td>
+                                    
+                                </tr>
+                            </g:each>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="name"></td>
+                                <td  valign="top" style="text-align:left;" class="value">
+                                    <g:link controller="taskDetailed" params="['primaryAsset.id':assetInstance?.id, 'taskType.id':6]" action="create">+Add ParentPM</g:link>
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetDetailed/importAssetTree.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetDetailed/importAssetTree.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetDetailed/importAssetTree.gsp	(revision 753)
@@ -0,0 +1,35 @@
+<html>
+    <head>
+        <meta name="layout" content="main" />
+        <title>Import Asset Tree</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Import Asset Tree</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:uploadForm action="importAssetTreeSave" onsubmit="return Lightbox.loading();">
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="file">File:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <input type="file" id="file" name="file" size="40"/>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:uploadForm>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetDetailed/search.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetDetailed/search.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetDetailed/search.gsp	(revision 753)
@@ -0,0 +1,165 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Asset Search</title>
+        <nav:resources override="true"/>
+        <filterpane:includes />
+        <export:resource />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+
+            <filterpane:currentCriteria domainBean="Asset"
+                                    action="search"
+                                    dateFormat="EEE, dd-MMM-yyyy"
+                                    removeImgDir="images" 
+                                    removeImgFile="bullet_delete.png"
+                                    title="Search"/>
+
+            <div class="paginateButtons">
+                Results: ${assetInstanceList.size()} / ${assetInstanceTotal}
+                <span class="searchButtons">
+                    <filterpane:filterButton text="Search" appliedText="Change Search" />
+                </span>
+            </div>
+
+            <jsUtil:toggleControl toggleId="options"
+                                                    imageId="optionsImg"
+                                                    closedImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_right.png')}"
+                                                    openImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_down.png')}"
+                                                    text="${g.message(code: 'default.options.text')}"
+                                                    />
+
+            <div id="options" style="display:none;">
+                <g:form method="post" action="setSearchParamsMax" >
+                    <g:hiddenField name="params" value="${filterParams}" />
+                    <div class="dialog">
+                        <table>
+                            <tbody>
+
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="max">Results per page:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <input type="text" maxlength="4" id="description" name="newMax" value="${params.max}"/>
+
+                                        <span class="buttons">
+                                            <g:actionSubmit action="setSearchParamsMax" class="go" value="Update" />
+                                        </span>
+                                    </td>
+                                </tr>
+
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="max">Asset Tree:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link action="exportAssetTree">
+                                            Export
+                                        </g:link>
+                                        /
+                                        <g:link action="exportAssetTreeTemplate">
+                                            Template
+                                        </g:link>
+                                        /
+                                        <g:link action="importAssetTree">
+                                            Import
+                                        </g:link>
+                                    </td>
+                                </tr>
+
+                            </tbody>
+                        </table>
+                    </div>
+                </g:form>
+                <export:formats  params="${filterParams}" formats="['csv', 'excel', 'pdf', 'rtf']"/>
+            </div>
+
+            <br />
+
+            <g:if test="${assetInstanceList.size() > 10}">
+                <g:if test="${assetInstanceTotal > assetInstanceList.size()}">
+                    <div class="paginateButtons">
+                        <g:paginate action="search" total="${assetInstanceTotal}" params="${filterParams}" />
+                    </div>
+                </g:if>
+            </g:if>
+
+            <g:if test="${assetInstanceList.size() > 0}">
+                <div class="list">
+                    <table>
+                        <thead>
+                            <tr>
+                            
+                                <g:sortableColumn property="id" title="Id" params="${filterParams}" />
+
+                                <g:sortableColumn property="name" title="Name" params="${filterParams}" />
+                            
+                                <g:sortableColumn property="description" title="Description" params="${filterParams}" />
+
+                                <g:sortableColumn property="isActive" title="Is Active" params="${filterParams}" />
+                            
+                                <g:sortableColumn property="section" title="Section" params="${filterParams}" />
+
+                                <th></th>
+                            
+                            </tr>
+                        </thead>
+                        <tbody>
+                        <g:each in="${assetInstanceList}" status="i" var="assetInstance">
+                            <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                            
+                                <td onclick='window.location = "${request.getContextPath()}/assetDetailed/show/${assetInstance.id}"'>
+                                    ${fieldValue(bean:assetInstance, field:'id')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/assetDetailed/show/${assetInstance.id}"'>
+                                    ${fieldValue(bean:assetInstance, field:'name')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/assetDetailed/show/${assetInstance.id}"'>
+                                    ${fieldValue(bean:assetInstance, field:'description')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/assetDetailed/show/${assetInstance.id}"'>
+                                    ${fieldValue(bean:assetInstance, field:'isActive')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/assetDetailed/show/${assetInstance.id}"'>
+                                    ${fieldValue(bean:assetInstance, field:'section')}
+                                </td>
+
+                                <td class="notClickable">
+                                    <g:link action="show" id="${assetInstance.id}">
+                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                    </g:link>
+                                </td>
+                            
+                            </tr>
+                        </g:each>
+                        </tbody>
+                    </table>
+                </div>
+            </g:if>
+            <div class="paginateButtons">
+                <g:paginate action="search" total="${assetInstanceTotal}" params="${filterParams}" />
+            </div>
+
+            <filterpane:filterPane domainBean="Asset"
+                                    title="Search"
+                                    action="search"
+                                    class="overlayPane"
+                                    excludeProperties=""
+                                    associatedProperties="section.name"
+                                    filterPropertyValues="${['section.name':[values:Section.list()] ]}" />
+        </div> <!-- end body div -->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetDetailed/show.gsp	(revision 753)
@@ -0,0 +1,174 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show Asset</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                        <tr class="prop">
+                            <td valign="top" class="groupHeader">
+                                <label for="name">Asset</label>
+                            </td>
+                            <td valign="top" class="value">
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="groupName">Id:</td>
+
+                            <td valign="top" class="value">${fieldValue(bean:assetInstance, field:'id')}</td>
+
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="groupName">Name:</td>
+
+                            <td  valign="top" style="text-align:left;" class="value">
+                                ${assetInstance.name.encodeAsHTML()}
+                            </td>
+
+                        </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">Description:</td>
+                                
+                                <td valign="top" class="value">${fieldValue(bean:assetInstance, field:'description')}</td>
+                                
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">Comment:</td>
+                                
+                                <td valign="top" class="value">${fieldValue(bean:assetInstance, field:'comment')}</td>
+                                
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">Is Active:</td>
+                                
+                                <td valign="top" class="value">${fieldValue(bean:assetInstance, field:'isActive')}</td>
+                                
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">Section:</td>
+                                
+                                <td valign="top" class="value"><g:link controller="sectionDetailed" action="show" id="${assetInstance?.section?.id}">${assetInstance?.section?.encodeAsHTML()}</g:link></td>
+                                
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">Extended Attributes</td>
+                                
+                                <td  valign="top" style="text-align:left;" class="value">
+                                </td>
+                                
+                            </tr>
+                        
+                            <g:each var="a" in="${assetInstance.assetExtendedAttributes.sort { p1, p2 -> p1.extendedAttributeType.name.compareToIgnoreCase(p2.extendedAttributeType.name) }}">
+                                <tr class="prop">
+                                    <td valign="top" class="groupName">
+                                        ${a.extendedAttributeType.name.encodeAsHTML()}:
+                                    </td>
+                                    
+                                    <td  valign="top" style="text-align:left;" class="value">
+                                        <g:link controller="assetExtendedAttributeDetailed" action="edit" id="${a.id}">
+                                            ${a.value.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                
+                                </tr>
+                            </g:each>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="assetSubItems">Asset Tree</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:render template="/shared/assetTree" />
+                                </td>
+                            </tr> 
+                            
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">Life Plan</td>
+                                
+                                <td  valign="top" style="text-align:left;" class="value">
+                                </td>
+                                
+                            </tr>
+
+                            <g:each var="t" in="${parentPMs}">
+                                <tr class="prop">
+                                    <td valign="top" class="name"></td>
+                                    
+                                    <td  valign="top" style="text-align:left;" class="value">
+                                        <g:link controller="taskDetailed" action="show" id="${t.id}">
+                                            Task #${t.id}
+                                        </g:link>
+                                        <g:if test="${t.approved}" >
+                                            <img  src="${resource(dir:'images/skin',file:'cog.png')}" alt="Approved" title="Approved" />
+                                        </g:if>
+                                        <g:if test="${t.taskRecurringSchedule?.enabled}" >
+                                            <img  src="${resource(dir:'images/skin',file:'arrow_refresh.png')}" alt="Recurrence Enabled" title="Recurrence Enabled" />
+                                        </g:if>
+                                        <g:if test="${t.taskStatus.id == 2}" >
+                                            <img  src="${resource(dir:'images/skin',file:'arrow_right.png')}" alt="In Progress" title="In Progress" />
+                                        </g:if>
+                                        <g:if test="${t.attentionFlag}" >
+                                            <img  src="${resource(dir:'images/skin',file:'flag_red.png')}" alt="Attention Flag" title="Attention Flag" />
+                                        </g:if>
+                                        <g:if test="${t.taskStatus.id == 3}" >
+                                            <img  src="${resource(dir:'images/skin',file:'tick.png')}" alt="Complete" title="Complete" />
+                                        </g:if>
+                                        <br />
+                                        ${fieldValue(bean:t, field:'description')}
+                                        <br />
+                                        <g:if test="${t.safetyRequirement}" >
+                                            <img  src="${resource(dir:'images/skin',file:'lightning.png')}" alt="Safety Requirement" title="Safety Requirement" />
+                                            Safety
+                                        </g:if>
+                                        <g:if test="${t.regulatoryRequirement}" >
+                                            <img  src="${resource(dir:'images/skin',file:'script_lightning.png')}" alt="Regulatory Requirement" title="Regulatory Requirement" />
+                                            Regulatory
+                                        </g:if>
+                                        <g:if test="${t.mandatoryRequirement}" >
+                                            <img  src="${resource(dir:'images/skin',file:'script.png')}" alt="Mandatory Requirement" title="Mandatory Requirement" />
+                                            Mandatory
+                                        </g:if>
+                                    </td>
+                                    
+                                </tr>
+                            </g:each>
+                        
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${assetInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetExtendedAttributeDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetExtendedAttributeDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetExtendedAttributeDetailed/create.gsp	(revision 753)
@@ -0,0 +1,60 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create AssetExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${assetExtendedAttributeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assetExtendedAttributeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="asset">Asset:</label>
+                                </td>
+
+                                <td valign="top" class="value">
+                                    <g:link controller="assetDetailed" action="show" id="${assetExtendedAttributeInstance?.asset?.id}">
+                                        <g:hiddenField name="asset.id" value="${assetExtendedAttributeInstance?.asset.id}" />
+                                        ${assetExtendedAttributeInstance?.asset?.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <g:select optionKey="id"
+                                                        from="${ExtendedAttributeType.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="extendedAttributeType.id"
+                                                        value="${assetExtendedAttributeInstance?.extendedAttributeType?.id}" >
+                                    </g:select>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetExtendedAttributeInstance,field:'value','errors')}">
+                                    <input type="text" maxlength="100" id="value" name="value" value="${fieldValue(bean:assetExtendedAttributeInstance,field:'value')}"/>
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetExtendedAttributeDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetExtendedAttributeDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetExtendedAttributeDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,74 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit AssetExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${assetExtendedAttributeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assetExtendedAttributeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${assetExtendedAttributeInstance?.id}" />
+                <input type="hidden" name="version" value="${assetExtendedAttributeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="value">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetExtendedAttributeInstance,field:'value','errors')}">
+                                    <input type="text" maxlength="100" id="value" name="value" value="${fieldValue(bean:assetExtendedAttributeInstance,field:'value')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetExtendedAttributeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${assetExtendedAttributeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="asset">Asset:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetExtendedAttributeInstance,field:'asset','errors')}">
+                                    <g:select optionKey="id" from="${Asset.list()}" name="asset.id" value="${assetExtendedAttributeInstance?.asset?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="extendedAttributeType">Extended Attribute Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetExtendedAttributeInstance,field:'extendedAttributeType','errors')}">
+                                    <g:select optionKey="id" from="${ExtendedAttributeType.list()}" name="extendedAttributeType.id" value="${assetExtendedAttributeInstance?.extendedAttributeType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetExtendedAttributeDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetExtendedAttributeDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetExtendedAttributeDetailed/show.gsp	(revision 753)
@@ -0,0 +1,67 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show AssetExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetExtendedAttributeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Value:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetExtendedAttributeInstance, field:'value')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetExtendedAttributeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Asset:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="assetDetailed" action="show" id="${assetExtendedAttributeInstance?.asset?.id}">${assetExtendedAttributeInstance?.asset?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Extended Attribute Type:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="extendedAttributeTypeDetailed" action="show" id="${assetExtendedAttributeInstance?.extendedAttributeType?.id}">${assetExtendedAttributeInstance?.extendedAttributeType?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${assetExtendedAttributeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/create.gsp	(revision 753)
@@ -0,0 +1,86 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create AssetSubItem</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${assetSubItemInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assetSubItemInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+
+                            <g:if test="${assetSubItemInstance?.parentItem}" >
+                                <g:hiddenField name="parentItem.id" value="${assetSubItemInstance.parentItem.id}" />
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="parentItem">Parent Item:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        ${assetSubItemInstance.parentItem.encodeAsHTML()}
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                            <g:if test="${assetInstance}" >
+                                <g:hiddenField name="asset.id" value="${assetInstance.id}" />
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="asset">Link with Asset:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        ${assetInstance.encodeAsHTML()}
+                                    </td>
+                                </tr>
+                            </g:if>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:assetSubItemInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:assetSubItemInstance,field:'description')}"/>
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:assetSubItemInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,201 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit AssetSubItem</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${assetSubItemInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assetSubItemInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${assetSubItemInstance?.id}" />
+                <input type="hidden" name="version" value="${assetSubItemInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="name">Asset Sub Item</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:assetSubItemInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:assetSubItemInstance,field:'description')}"/>
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:assetSubItemInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${assetSubItemInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">Extended Attributes</td>
+                                <td  valign="top" style="text-align:left;" class="value">
+                                </td>
+                            </tr>
+                            
+                            <g:each var="a" in="${assetSubItemInstance.assetSubItemExtendedAttributes.sort { p1, p2 -> p1.extendedAttributeType.name.compareToIgnoreCase(p2.extendedAttributeType.name) }}">
+                                <tr class="prop">
+                                    <td valign="top" class="groupName">
+                                        ${a.extendedAttributeType.name.encodeAsHTML()}:
+                                    </td>
+
+                                    <td  valign="top" style="text-align:left;" class="value">
+                                        <g:link controller="assetSubItemExtendedAttributeDetailed" action="edit" id="${a.id}">
+                                            ${a.value.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+
+                                </tr>
+                            </g:each>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                </td>
+                                <td valign="top" style="text-align:left;" class="value">
+                                    <g:link controller="assetSubItemExtendedAttributeDetailed" params="['assetSubItem.id':assetSubItemInstance?.id]" action="create">+Add Extended Attribute</g:link>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="name">Asset Tree</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr> 
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">Assets:</td>
+
+                                <td  valign="top" style="text-align:left;" class="value">
+                                    <g:if test="${assetSubItemInstance.parentItem}" >
+                                        N/A (Assigned to parent item)
+                                    </g:if>
+                                    <g:else>
+                                        <g:if test="${assetSubItemInstance.assets}">
+                                            <ul>
+                                            <g:each var="a" in="${ assetSubItemInstance.assets.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
+                                                <li><g:link controller="assetDetailed" action="show" id="${a.id}">${a?.encodeAsHTML()}</g:link></li>
+                                            </g:each>
+                                            </ul>
+                                        </g:if>
+                                        <g:else>
+                                            May be assigned via asset edit view.
+                                        </g:else>
+                                    </g:else>
+                                </td>
+
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="parentItem">Parent Item:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemInstance,field:'parentItem','errors')}">
+                                    <g:if test="${assetSubItemInstance.assets}">
+                                        Level 1 sub item (Assigned directly to assets)
+                                    </g:if>
+                                    <g:else>
+                                        <g:select optionKey="id" from="${possibleParentItems}" name="parentItem.id" value="${assetSubItemInstance?.parentItem?.id}" noSelection="['null':'--None--']"></g:select>
+                                    </g:else>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="subItems">Sub Items:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemInstance,field:'subItems','errors')}">
+                                    
+<ul>
+<g:each var="s" in="${assetSubItemInstance?.subItems?}">
+    <li><g:link controller="assetSubItemDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="assetSubItemDetailed" params="['parentItem.id':assetSubItemInstance?.id]" action="create">+Add Sub Item</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="name">Maintenance Actions</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr> 
+                        
+                            <g:each var="m" in="${assetSubItemInstance?.maintenanceActions?}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                    </td>
+                                    <td valign="top" class="value ${hasErrors(bean:assetSubItemInstance,field:'maintenanceActions','errors')}">
+                                        <g:link controller="maintenanceActionDetailed" action="show" id="${m.id}">${m?.encodeAsHTML()}</g:link></li>
+                                    </td>
+                                </tr>
+                            </g:each>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:link controller="maintenanceActionDetailed" params="['assetSubItem.id':assetSubItemInstance?.id]" action="create">+Add Maintenance Action</g:link>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/search.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/search.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/search.gsp	(revision 753)
@@ -0,0 +1,138 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>AssetSubItem Search</title>
+        <nav:resources override="true"/>
+        <filterpane:includes />
+        <export:resource />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+
+            <filterpane:currentCriteria domainBean="AssetSubItem"
+                                    action="search"
+                                    dateFormat="EEE, dd-MMM-yyyy"
+                                    removeImgDir="images" 
+                                    removeImgFile="bullet_delete.png"
+                                    title="Search"/>
+
+            <div class="paginateButtons">
+                Results: ${assetSubItemInstanceList.size()} / ${assetSubItemInstanceTotal}
+                <span class="searchButtons">
+                    <filterpane:filterButton text="Search" appliedText="Change Search" />
+                </span>
+            </div>
+
+            <jsUtil:toggleControl toggleId="options"
+                                                    imageId="optionsImg"
+                                                    closedImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_right.png')}"
+                                                    openImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_down.png')}"
+                                                    text="${g.message(code: 'default.options.text')}"
+                                                    />
+
+            <div id="options" style="display:none;">
+                <g:form method="post" action="setSearchParamsMax" >
+                    <g:hiddenField name="params" value="${filterParams}" />
+                    <div class="dialog">
+                        <table>
+                            <tbody>
+
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="max">Results per page:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <input type="text" maxlength="4" id="description" name="newMax" value="${params.max}"/>
+
+                                        <span class="buttons">
+                                            <g:actionSubmit action="setSearchParamsMax" class="go" value="Update" />
+                                        </span>
+                                    </td>
+                                </tr>
+
+                            </tbody>
+                        </table>
+                    </div>
+                </g:form>
+                <export:formats  params="${filterParams}" formats="['csv', 'excel', 'pdf', 'rtf']"/>
+            </div>
+
+            <br />
+
+            <g:if test="${assetSubItemInstanceList.size() > 10}">
+                <g:if test="${assetSubItemInstanceTotal > assetSubItemInstanceList.size()}">
+                    <div class="paginateButtons">
+                        <g:paginate action="search" total="${assetSubItemInstanceTotal}" params="${filterParams}" />
+                    </div>
+                </g:if>
+            </g:if>
+
+            <g:if test="${assetSubItemInstanceList.size() > 0}">
+                <div class="list">
+                    <table>
+                        <thead>
+                            <tr>
+                            
+                                <g:sortableColumn property="id" title="Id" params="${filterParams}" />
+
+                                <g:sortableColumn property="name" title="Name" params="${filterParams}" />
+                            
+                                <g:sortableColumn property="description" title="Description" params="${filterParams}" />
+
+                                <g:sortableColumn property="isActive" title="Is Active" params="${filterParams}" />
+
+                                <th></th>
+                            
+                            </tr>
+                        </thead>
+                        <tbody>
+                        <g:each in="${assetSubItemInstanceList}" status="i" var="assetSubItemInstance">
+                            <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                            
+                                <td onclick='window.location = "${request.getContextPath()}/assetSubItemDetailed/show/${assetSubItemInstance.id}"'>
+                                    ${fieldValue(bean:assetSubItemInstance, field:'id')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/assetSubItemDetailed/show/${assetSubItemInstance.id}"'>
+                                    ${fieldValue(bean:assetSubItemInstance, field:'name')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/assetSubItemDetailed/show/${assetSubItemInstance.id}"'>
+                                    ${fieldValue(bean:assetSubItemInstance, field:'description')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/assetSubItemDetailed/show/${assetSubItemInstance.id}"'>
+                                    ${fieldValue(bean:assetSubItemInstance, field:'isActive')}
+                                </td>
+
+                                <td class="notClickable">
+                                    <g:link action="show" id="${assetSubItemInstance.id}">
+                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                    </g:link>
+                                </td>
+                            
+                            </tr>
+                        </g:each>
+                        </tbody>
+                    </table>
+                </div>
+            </g:if>
+            <div class="paginateButtons">
+                <g:paginate action="search" total="${assetSubItemInstanceTotal}" params="${filterParams}" />
+            </div>
+
+            <filterpane:filterPane domainBean="AssetSubItem"
+                                    title="Search"
+                                    action="search"
+                                    class="overlayPane"
+                                    excludeProperties="" />
+        </div> <!-- end body div -->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetSubItemDetailed/show.gsp	(revision 753)
@@ -0,0 +1,174 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show AssetSubItem</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+                        
+                        <tr class="prop">
+                            <td valign="top" class="groupHeader">
+                                <label for="name">Asset Sub Item</label>
+                            </td>
+                            <td valign="top" class="value">
+                            </td>
+                        </tr>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="groupName">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetSubItemInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="groupName">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetSubItemInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="groupName">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetSubItemInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="groupName">Comment:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetSubItemInstance, field:'comment')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="groupName">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetSubItemInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                        
+                        <tr class="prop">
+                            <td valign="top" class="groupHeader">Extended Attributes</td>
+                            <td  valign="top" style="text-align:left;" class="value">
+                            </td>
+                        </tr>
+                        
+                        <g:each var="a" in="${assetSubItemInstance.assetSubItemExtendedAttributes.sort { p1, p2 -> p1.extendedAttributeType.name.compareToIgnoreCase(p2.extendedAttributeType.name) }}">
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    ${a.extendedAttributeType.name.encodeAsHTML()}:
+                                </td>
+
+                                <td  valign="top" style="text-align:left;" class="value">
+                                    <g:link controller="assetSubItemExtendedAttributeDetailed" action="edit" id="${a.id}">
+                                        ${a.value.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+
+                            </tr>
+                        </g:each>
+                        
+                        <tr class="prop">
+                            <td valign="top" class="groupHeader">
+                                <label for="name">Asset Tree</label>
+                            </td>
+                            <td valign="top" class="value">
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="groupName">Assets:</td>
+
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <g:if test="${assetSubItemInstance.parentItem}" >
+                                    N/A (Assigned to parent item)
+                                </g:if>
+                                <g:else>
+                                    <g:if test="${assetSubItemInstance.assets}">
+                                        <ul>
+                                        <g:each var="a" in="${ assetSubItemInstance.assets.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
+                                            <li><g:link controller="assetDetailed" action="show" id="${a.id}">${a?.encodeAsHTML()}</g:link></li>
+                                        </g:each>
+                                        </ul>
+                                    </g:if>
+                                    <g:else>
+                                        May be assigned via asset edit view.
+                                    </g:else>
+                                </g:else>
+                            </td>
+
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="groupName">Parent Item:</td>
+                            
+                            <td valign="top" class="value">
+                                <g:if test="${assetSubItemInstance.assets}">
+                                     Level 1 sub item (Assigned directly to assets)
+                                </g:if>
+                                <g:else>
+                                    <g:link controller="assetSubItemDetailed" action="show" id="${assetSubItemInstance?.parentItem?.id}">
+                                        ${assetSubItemInstance?.parentItem?.encodeAsHTML()}
+                                    </g:link>
+                                </g:else>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="groupName">Sub Items:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="s" in="${assetSubItemInstance.subItems}">
+                                    <li><g:link controller="assetSubItemDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                        
+                        <tr class="prop">
+                            <td valign="top" class="groupHeader">
+                                <label for="name">Maintenance Actions</label>
+                            </td>
+                            <td valign="top" class="value">
+                            </td>
+                        </tr>
+                    
+                        <g:each var="m" in="${assetSubItemInstance.maintenanceActions}">
+                            <tr class="prop">
+                                <td valign="top" class="name"></td>
+                                <td  valign="top" style="text-align:left;" class="value">
+                                    <g:link controller="maintenanceActionDetailed" action="show" id="${m.id}">${m?.encodeAsHTML()}</g:link>
+                                </td>
+                            </tr>
+                        </g:each>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${assetSubItemInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetSubItemExtendedAttributeDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetSubItemExtendedAttributeDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetSubItemExtendedAttributeDetailed/create.gsp	(revision 753)
@@ -0,0 +1,61 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create AssetSubItemExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${assetSubItemExtendedAttributeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assetSubItemExtendedAttributeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            
+                            <tr class="prop">
+                              <td valign="top" class="name">
+                                      <label for="asset">Asset Sub Item:</label>
+                                 </td>
+
+                                 <td valign="top" class="value">
+                                     <g:link controller="assetSubItemDetailed" action="show" id="${assetSubItemExtendedAttributeInstance?.assetSubItem?.id}">
+                                          <g:hiddenField name="assetSubItem.id" value="${assetSubItemExtendedAttributeInstance?.assetSubItem.id}" />
+                                          ${assetSubItemExtendedAttributeInstance?.assetSubItem?.encodeAsHTML()}
+                                     </g:link>
+                                 </td>
+                             </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <g:select optionKey="id"
+                                                        from="${ExtendedAttributeType.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="extendedAttributeType.id"
+                                                        value="${assetSubItemExtendedAttributeInstance?.extendedAttributeType?.id}" >
+                                    </g:select>
+
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemExtendedAttributeInstance,field:'value','errors')}">
+                                    <input type="text" maxlength="100" id="value" name="value" value="${fieldValue(bean:assetSubItemExtendedAttributeInstance,field:'value')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetSubItemExtendedAttributeDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetSubItemExtendedAttributeDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetSubItemExtendedAttributeDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,74 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit AssetSubItemExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${assetSubItemExtendedAttributeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assetSubItemExtendedAttributeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${assetSubItemExtendedAttributeInstance?.id}" />
+                <input type="hidden" name="version" value="${assetSubItemExtendedAttributeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="value">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemExtendedAttributeInstance,field:'value','errors')}">
+                                    <input type="text" maxlength="100" id="value" name="value" value="${fieldValue(bean:assetSubItemExtendedAttributeInstance,field:'value')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemExtendedAttributeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${assetSubItemExtendedAttributeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="assetSubItem">Asset Sub Item:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemExtendedAttributeInstance,field:'assetSubItem','errors')}">
+                                    <g:select optionKey="id" from="${AssetSubItem.list()}" name="assetSubItem.id" value="${assetSubItemExtendedAttributeInstance?.assetSubItem?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="extendedAttributeType">Extended Attribute Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assetSubItemExtendedAttributeInstance,field:'extendedAttributeType','errors')}">
+                                    <g:select optionKey="id" from="${ExtendedAttributeType.list()}" name="extendedAttributeType.id" value="${assetSubItemExtendedAttributeInstance?.extendedAttributeType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assetSubItemExtendedAttributeDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assetSubItemExtendedAttributeDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assetSubItemExtendedAttributeDetailed/show.gsp	(revision 753)
@@ -0,0 +1,67 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show AssetSubItemExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetSubItemExtendedAttributeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Value:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetSubItemExtendedAttributeInstance, field:'value')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:assetSubItemExtendedAttributeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Asset Sub Item:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="assetSubItemDetailed" action="show" id="${assetSubItemExtendedAttributeInstance?.assetSubItem?.id}">${assetSubItemExtendedAttributeInstance?.assetSubItem?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Extended Attribute Type:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="extendedAttributeTypeDetailed" action="show" id="${assetSubItemExtendedAttributeInstance?.extendedAttributeType?.id}">${assetSubItemExtendedAttributeInstance?.extendedAttributeType?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${assetSubItemExtendedAttributeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assignedGroupDetailed/_personsInGroup.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assignedGroupDetailed/_personsInGroup.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assignedGroupDetailed/_personsInGroup.gsp	(revision 753)
@@ -0,0 +1,22 @@
+
+<table>
+    <tbody>
+        <tr class="prop">
+            <td valign="top" class="name">
+                <label for="persons">Persons in group (${personGroup.encodeAsHTML()}):</label>
+            </td>
+            <td valign="top" class="value">
+                <ul>
+                    <g:if test="${personsInGroup.size() > 0}">
+                        <g:each var="a" in="${personsInGroup}">
+                            <li>${a?.encodeAsHTML()}</li>
+                        </g:each>
+                    </g:if>
+                    <g:else>
+                        <li>None</li>
+                    </g:else>
+                </ul>
+            </td>
+        </tr>
+    </tbody>
+</table>
Index: branches/features/taskProcedureRework/grails-app/views/assignedGroupDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assignedGroupDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assignedGroupDetailed/create.gsp	(revision 753)
@@ -0,0 +1,87 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create AssignedGroup</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Assigned Group</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${assignedGroupInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assignedGroupInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <g:hiddenField name="task.id" value="${assignedGroupInstance?.task?.id}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="task">Task:</label>
+                                </td>
+                                <td valign="top" class="name">
+                                    <g:link controller="taskDetailed" action="show" id="${assignedGroupInstance.task.id}" >
+                                        ${assignedGroupInstance?.task.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="personGroup">Group:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assignedGroupInstance,field:'personGroup','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${PersonGroup.list().sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="personGroup.id"
+                                                        value="${assignedGroupInstance?.personGroup?.id}"
+                                                        onchange="${remoteFunction(action:'personsInGroup', update:'personsInGroup', params: '\'personGroup.id=\' + this.value' )}">
+                                    </g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="durationHour">Estimated Duration:</label>
+                                </td>
+
+                                <td valign="top" class="value">
+                                    <input class="time ${hasErrors(bean:assignedGroupInstance,field:'estimatedHour','errors')}"
+                                        type="text" id="estimatedHour" name="estimatedHour" 
+                                        value="${fieldValue(bean:assignedGroupInstance,field:'estimatedHour')}" />
+                                    :
+                                    <input class="time ${hasErrors(bean:assignedGroupInstance,field:'estimatedMinute','errors')}"
+                                        type="text" id="estimatedMinute" name="estimatedMinute" 
+                                        value="${fieldValue(bean:assignedGroupInstance,field:'estimatedMinute')}" />
+                                    <g:helpBalloon code="assignedGroup.estimatedDuration" />
+                                </td> 
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+
+            <br />
+
+            <div id="personsInGroup" class="dialog">
+                <g:render template="personsInGroup" />
+            </div>
+
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assignedGroupDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assignedGroupDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assignedGroupDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,88 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit AssignedGroup</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Assigned Group</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${assignedGroupInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assignedGroupInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <g:hiddenField name="id" value="${assignedGroupInstance?.id}" />
+                <g:hiddenField name="task.id" value="${assignedGroupInstance?.task?.id}" />
+                <g:hiddenField name="version" value="${assignedGroupInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="task">Task:</label>
+                                </td>
+                                <td valign="top" class="name">
+                                    <g:link controller="taskDetailed" action="show" id="${assignedGroupInstance.task.id}" >
+                                        ${assignedGroupInstance?.task.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="personGroup">Group:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assignedGroupInstance,field:'personGroup','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${PersonGroup.list().sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="personGroup.id"
+                                                        value="${assignedGroupInstance?.personGroup?.id}"
+                                                        onchange="${remoteFunction(action:'personsInGroup', update:'personsInGroup', params: '\'personGroup.id=\' + this.value' )}">
+                                    </g:select>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="durationHour">Estimated Duration:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <input class="time ${hasErrors(bean:assignedGroupInstance,field:'estimatedHour','errors')}"
+                                        type="text" id="estimatedHour" name="estimatedHour" 
+                                        value="${fieldValue(bean:assignedGroupInstance,field:'estimatedHour')}" />
+                                    :
+                                    <input class="time ${hasErrors(bean:assignedGroupInstance,field:'estimatedMinute','errors')}"
+                                        type="text" id="estimatedMinute" name="estimatedMinute" 
+                                        value="${fieldValue(bean:assignedGroupInstance,field:'estimatedMinute')}" />
+                                    <g:helpBalloon code="assignedGroup.estimatedDuration" />
+                                </td> 
+                            </tr>
+
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+
+            <br />
+
+            <div id="personsInGroup" class="dialog">
+                <g:render template="personsInGroup" />
+            </div>
+
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assignedPersonDetailed/_groupsForPerson.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assignedPersonDetailed/_groupsForPerson.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assignedPersonDetailed/_groupsForPerson.gsp	(revision 753)
@@ -0,0 +1,22 @@
+
+<table>
+    <tbody>
+        <tr class="prop">
+            <td valign="top" class="name">
+                <label for="groups">Groups for person (${person.encodeAsHTML()}):</label>
+            </td>
+            <td valign="top" class="value">
+                <ul>
+                    <g:if test="${groupsForPerson.size() > 0}">
+                        <g:each var="a" in="${groupsForPerson}">
+                            <li>${a?.encodeAsHTML()}</li>
+                        </g:each>
+                    </g:if>
+                    <g:else>
+                        <li>None</li>
+                    </g:else>
+                </ul>
+            </td>
+        </tr>
+    </tbody>
+</table>
Index: branches/features/taskProcedureRework/grails-app/views/assignedPersonDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assignedPersonDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assignedPersonDetailed/create.gsp	(revision 753)
@@ -0,0 +1,86 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create AssignedPerson</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Assigned Person</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${assignedPersonInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assignedPersonInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <g:hiddenField name="task.id" value="${assignedPersonInstance?.task?.id}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="task">Task:</label>
+                                </td>
+                                <td valign="top" class="name">
+                                    <g:link controller="taskDetailed" action="show" id="${assignedPersonInstance.task.id}" >
+                                        ${assignedPersonInstance?.task.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="person">Person:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assignedPersonInstance,field:'person','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${Person.list().sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }}"
+                                                        name="person.id"
+                                                        value="${assignedPersonInstance?.person?.id}"
+                                                        onchange="${remoteFunction(action:'groupsForPerson', update:'groupsForPerson', params: '\'person.id=\' + this.value' )}">
+                                    </g:select>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="durationHour">Estimated Duration:</label>
+                                </td>
+
+                                <td valign="top" class="value">
+                                    <input class="time ${hasErrors(bean:assignedPersonInstance,field:'estimatedHour','errors')}" 
+                                        type="text" id="estimatedHour" name="estimatedHour" 
+                                        value="${fieldValue(bean:assignedPersonInstance,field:'estimatedHour')}" />
+                                    :
+                                    <input class="time ${hasErrors(bean:assignedPersonInstance,field:'estimatedMinute','errors')}" 
+                                        type="text" id="estimatedMinute" name="estimatedMinute" 
+                                        value="${fieldValue(bean:assignedPersonInstance,field:'estimatedMinute')}" />
+                                    <g:helpBalloon code="assignedPerson.estimatedDuration" />
+                                </td> 
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+
+            <br />
+
+            <div id="groupsForPerson" class="dialog">
+                <g:render template="groupsForPerson" />
+            </div>
+
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/assignedPersonDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/assignedPersonDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/assignedPersonDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,88 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit AssignedPerson</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Assigned Person</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${assignedPersonInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${assignedPersonInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <g:hiddenField name="id" value="${assignedPersonInstance?.id}" />
+                <g:hiddenField name="task.id" value="${assignedPersonInstance?.task?.id}" />
+                <g:hiddenField name="version" value="${assignedPersonInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="task">Task:</label>
+                                </td>
+                                <td valign="top" class="name">
+                                    <g:link controller="taskDetailed" action="show" id="${assignedPersonInstance.task.id}" >
+                                        ${assignedPersonInstance?.task.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="person">Person:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:assignedPersonInstance,field:'person','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${Person.list().sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }}"
+                                                        name="person.id"
+                                                        value="${assignedPersonInstance?.person?.id}"
+                                                        onchange="${remoteFunction(action:'groupsForPerson', update:'groupsForPerson', params: '\'person.id=\' + this.value' )}">
+                                    </g:select>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="durationHour">Estimated Duration:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <input class="time ${hasErrors(bean:assignedPersonInstance,field:'estimatedHour','errors')}" 
+                                        type="text" id="estimatedHour" name="estimatedHour" 
+                                        value="${fieldValue(bean:assignedPersonInstance,field:'estimatedHour')}" />
+                                    :
+                                    <input class="time ${hasErrors(bean:assignedPersonInstance,field:'estimatedMinute','errors')}" 
+                                        type="text" id="estimatedMinute" name="estimatedMinute" 
+                                        value="${fieldValue(bean:assignedPersonInstance,field:'estimatedMinute')}" />
+                                    <g:helpBalloon code="assignedPerson.estimatedDuration" />
+                                </td> 
+                            </tr>
+
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+
+            <br />
+
+            <div id="groupsForPerson" class="dialog">
+                <g:render template="groupsForPerson" />
+            </div>
+
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/authority/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/authority/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/authority/create.gsp	(revision 753)
@@ -0,0 +1,50 @@
+<head>
+    <meta name="layout" content="main" />
+    <title>Create Authority</title>
+</head>
+
+<body>
+
+    <div class="nav">
+        <span class="menuButton"><g:link class="list" action="list">Authority List</g:link></span>
+    </div>
+
+    <div class="body">
+
+        <h1>Create Authority</h1>
+        <g:if test="${flash.message}">
+        <div class="message">${flash.message}</div>
+        </g:if>
+        <g:hasErrors bean="${authority}">
+        <div class="errors">
+        <g:renderErrors bean="${authority}" as="list" />
+        </div>
+        </g:hasErrors>
+
+        <g:form action="save">
+        <div class="dialog">
+        <table>
+        <tbody>
+            <tr class="prop">
+                <td valign="top" class="name"><label for="authority">Authority Name:</label></td>
+                <td valign="top" class="value ${hasErrors(bean:authority,field:'authority','errors')}">
+                    <input type="text" id="authority" name="authority" value="${authority?.authority?.encodeAsHTML()}"/>
+                </td>
+            </tr>
+
+            <tr class="prop">
+                <td valign="top" class="name"><label for="description">Description:</label></td>
+                <td valign="top" class="value ${hasErrors(bean:authority,field:'description','errors')}">
+                    <input type="text" id="description" name="description" value="${authority?.description?.encodeAsHTML()}"/>
+                </td>
+            </tr>
+        </tbody>
+        </table>
+        </div>
+
+        <div class="buttons">
+            <span class="button"><input class="save" type="submit" value="Create" /></span>
+        </div>
+        </g:form>
+    </div>
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/authority/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/authority/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/authority/edit.gsp	(revision 753)
@@ -0,0 +1,68 @@
+<head>
+    <meta name="layout" content="main" />
+    <title>Edit Authority</title>
+</head>
+
+<body>
+
+    <div class="nav">
+        <span class="menuButton"><g:link class="list" action="list">Authority List</g:link></span>
+        <span class="menuButton"><g:link class="create" action="create">New Authority</g:link></span>
+    </div>
+
+    <div class="body">
+        <h1>Edit Authority</h1>
+        <g:if test="${flash.message}">
+        <div class="message">${flash.message}</div>
+        </g:if>
+        <g:hasErrors bean="${authority}">
+        <div class="errors">
+            <g:renderErrors bean="${authority}" as="list" />
+        </div>
+        </g:hasErrors>
+        <div class="prop">
+            <span class="name">ID:</span>
+            <span class="value">${authority.id}</span>
+        </div>
+        <g:form>
+            <input type="hidden" name="id" value="${authority.id}" />
+            <input type="hidden" name="version" value="${authority.version}" />
+            <div class="dialog">
+            <table>
+            <tbody>
+                <tr class="prop">
+                    <td valign="top" class="name"><label for="authority">Authority Name:</label></td>
+                    <td valign="top" class="value ${hasErrors(bean:authority,field:'authority','errors')}">
+                        <input type="text" id="authority" name="authority" value="${authority.authority?.encodeAsHTML()}"/>
+                    </td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name"><label for="description">Description:</label></td>
+                    <td valign="top" class="value ${hasErrors(bean:authority,field:'description','errors')}">
+                        <input type="text" id="description" name="description" value="${authority.description?.encodeAsHTML()}"/>
+                    </td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name"><label for="persons">Persons:</label></td>
+                    <td valign="top" class="value ${hasErrors(bean:authority,field:'persons','errors')}">
+                        <ul>
+                        <g:each var="p" in="${authority.persons?}">
+                            <li>${p}</li>
+                        </g:each>
+                        </ul>
+                    </td>
+                </tr>
+            </tbody>
+            </table>
+            </div>
+
+            <div class="buttons">
+                <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+            </div>
+
+        </g:form>
+    </div>
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/authority/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/authority/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/authority/list.gsp	(revision 753)
@@ -0,0 +1,48 @@
+<head>
+    <meta name="layout" content="main" />
+    <title>Authority List</title>
+</head>
+
+<body>
+
+    <div class="nav">
+        <span class="menuButton"><g:link class="create" action="create">New Authority</g:link></span>
+    </div>
+
+    <div class="body">
+        <h1>Authority List</h1>
+        <g:if test="${flash.message}">
+        <div class="message">${flash.message}</div>
+        </g:if>
+        <div class="list">
+            <table>
+            <thead>
+                <tr>
+                    <g:sortableColumn property="id" title="ID" />
+                    <g:sortableColumn property="authority" title="Authority Name" />
+                    <g:sortableColumn property="description" title="Description" />
+                    <th>&nbsp;</th>
+                </tr>
+            </thead>
+            <tbody>
+            <g:each in="${authorityList}" status="i" var="authority">
+                <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                    <td>${authority.id}</td>
+                    <td>${authority.authority?.encodeAsHTML()}</td>
+                    <td>${authority.description?.encodeAsHTML()}</td>
+                    <td class="actionButtons">
+                        <span class="actionButton">
+                            <g:link action="show" id="${authority.id}">Show</g:link>
+                        </span>
+                    </td>
+                </tr>
+            </g:each>
+            </tbody>
+            </table>
+        </div>
+
+        <div class="paginateButtons">
+            <g:paginate total="${Authority.count()}" />
+        </div>
+    </div>
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/authority/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/authority/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/authority/show.gsp	(revision 753)
@@ -0,0 +1,56 @@
+<head>
+    <meta name="layout" content="main" />
+    <title>Show Authority</title>
+</head>
+
+<body>
+
+    <div class="nav">
+        <span class="menuButton"><g:link class="list" action="list">Authority List</g:link></span>
+        <span class="menuButton"><g:link class="create" action="create">New Authority</g:link></span>
+    </div>
+
+    <div class="body">
+        <h1>Show Authority</h1>
+        <g:if test="${flash.message}">
+        <div class="message">${flash.message}</div>
+        </g:if>
+        <div class="dialog">
+            <table>
+            <tbody>
+
+                <tr class="prop">
+                    <td valign="top" class="name">ID:</td>
+                    <td valign="top" class="value">${authority.id}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Authority Name:</td>
+                    <td valign="top" class="value">${authority.authority}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Description:</td>
+                    <td valign="top" class="value">${authority.description}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Persons:</td>
+                    <td valign="top" class="value">${authority.persons}</td>
+                </tr>
+
+            </tbody>
+            </table>
+        </div>
+
+        <div class="buttons">
+            <g:form>
+                <input type="hidden" name="id" value="${authority?.id}" />
+                <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+            </g:form>
+        </div>
+
+    </div>
+
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/contactDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/contactDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/contactDetailed/create.gsp	(revision 753)
@@ -0,0 +1,94 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Contact</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Contact</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${contactInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${contactInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            
+                            <g:if test="${contactInstance.supplier}">
+                                <g:hiddenField name="supplier.id" value="${contactInstance.supplier.id}"/>
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="supplier">Supplier:</label>
+                                    </td>
+                                    <td valign="top" class="value ${hasErrors(bean:contactInstance,field:'supplier','errors')}">
+                                        <g:link controller="supplierDetailed" action="show" id="${contactInstance.supplier.id}">
+                                            ${contactInstance.supplier.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr>
+                            </g:if>
+                            
+                            <g:if test="${contactInstance.person}">
+                                <g:hiddenField name="person.id" value="${contactInstance.person.id}"/>
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="person">Person:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link controller="person" action="show" id="${contactInstance.person.id}">
+                                            ${contactInstance.person.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr> 
+                            </g:if>
+                            
+                            <g:if test="${contactInstance.site}">
+                                <g:hiddenField name="site.id" value="${contactInstance.site.id}"/>
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="site">Site:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link controller="siteDetailed" action="show" id="${contactInstance.site.id}">
+                                            ${contactInstance.site.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr> 
+                            </g:if>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="contactType">Contact Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:contactInstance,field:'contactType','errors')}">
+                                    <g:select optionKey="id" from="${ContactType.list()}" name="contactType.id" value="${contactInstance?.contactType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="email">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:contactInstance,field:'value','errors')}">
+                                    <input type="text" id="value" name="value" value="${fieldValue(bean:contactInstance,field:'value')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/contactDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/contactDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/contactDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,98 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit Contact</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Contact</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${contactInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${contactInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${contactInstance?.id}" />
+                <input type="hidden" name="version" value="${contactInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+
+                            <g:if test="${contactInstance.supplier}">
+                                <g:hiddenField name="supplier.id" value="${contactInstance.supplier.id}"/>
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="supplier">Supplier:</label>
+                                    </td>
+                                    <td valign="top" class="value ${hasErrors(bean:contactInstance,field:'supplier','errors')}">
+                                        <g:link controller="supplierDetailed" action="show" id="${contactInstance.supplier.id}">
+                                            ${contactInstance.supplier.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                            <g:if test="${contactInstance.person}">
+                                <g:hiddenField name="person.id" value="${contactInstance.person.id}"/>
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="person">Person:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link controller="person" action="show" id="${contactInstance.person.id}">
+                                            ${contactInstance.person.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                            <g:if test="${contactInstance.site}">
+                                <g:hiddenField name="site.id" value="${contactInstance.site.id}"/>
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="site">Site:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link controller="siteDetailed" action="show" id="${contactInstance.site.id}">
+                                            ${contactInstance.site.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="contactType">Contact Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:contactInstance,field:'contactType','errors')}">
+                                    <g:select optionKey="id" from="${ContactType.list()}" name="contactType.id" value="${contactInstance?.contactType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="email">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:contactInstance,field:'value','errors')}">
+                                    <input type="text" id="value" name="value" value="${fieldValue(bean:contactInstance,field:'value')}"/>
+                                </td>
+                            </tr>
+
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/contactDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/contactDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/contactDetailed/show.gsp	(revision 753)
@@ -0,0 +1,73 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show Contact</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Contact</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            <td valign="top" class="value">${fieldValue(bean:contactInstance, field:'id')}</td>
+                        </tr>
+
+                        <g:if test="${contactInstance.supplier}">
+                            <tr class="prop">
+                                <td valign="top" class="name">Supplier:</td>
+
+                                <td valign="top" class="value"><g:link controller="supplierDetailed" action="show" id="${contactInstance.supplier.id}">${contactInstance.supplier.encodeAsHTML()}</g:link></td>
+
+                            </tr>
+                        </g:if>
+
+                        <g:if test="${contactInstance.person}">
+                            <tr class="prop">
+                                <td valign="top" class="name">Person:</td>
+
+                                <td valign="top" class="value"><g:link controller="person" action="show" id="${contactInstance.person.id}">${contactInstance.person.encodeAsHTML()}</g:link></td>
+
+                            </tr>
+                        </g:if>
+
+                        <g:if test="${contactInstance.site}">
+                            <tr class="prop">
+                                <td valign="top" class="name">Site:</td>
+
+                                <td valign="top" class="value"><g:link controller="siteDetailed" action="show" id="${contactInstance.site.id}">${contactInstance.site.encodeAsHTML()}</g:link></td>
+
+                            </tr>
+                        </g:if>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Contact Type:</td>
+                            <td valign="top" class="value">${fieldValue(bean:contactInstance, field:'contactType')}</td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Value:</td>
+                            <td valign="top" class="value">${fieldValue(bean:contactInstance, field:'value')}</td>
+                        </tr>
+
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${contactInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/create.gsp	(revision 753)
@@ -0,0 +1,78 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create CostCode</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${costCodeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${costCodeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:costCodeInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:costCodeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="purchasingGroup">Purchasing Group:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:costCodeInstance,field:'purchasingGroup','errors')}">
+                                    <g:select optionKey="id"
+                                                    from="${PurchasingGroup.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                    name="purchasingGroup.id"
+                                                    value="${costCodeInstance?.purchasingGroup?.id}" >
+                                    </g:select>
+                                    <p>
+                                        <g:link controller="purchasingGroupDetailed" action="create">+Add Group</g:link>
+                                    </p>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:costCodeInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:costCodeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:costCodeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${costCodeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,82 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit CostCode</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${costCodeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${costCodeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${costCodeInstance?.id}" />
+                <input type="hidden" name="version" value="${costCodeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:costCodeInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:costCodeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="purchasingGroup">Purchasing Group:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:costCodeInstance,field:'purchasingGroup','errors')}">
+                                    <g:select optionKey="id"
+                                                    from="${PurchasingGroup.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                    name="purchasingGroup.id"
+                                                    value="${costCodeInstance?.purchasingGroup?.id}" >
+                                    </g:select>
+                                    <p>
+                                        <g:link controller="purchasingGroupDetailed" action="create">+Add Group</g:link>
+                                    </p>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:costCodeInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:costCodeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:costCodeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${costCodeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/list.gsp	(revision 753)
@@ -0,0 +1,75 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>CostCode List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                            <g:sortableColumn property="purchasingGroup" title="Group" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${costCodeInstanceList}" status="i" var="costCodeInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/costCodeDetailed/show/${costCodeInstance.id}"'>
+                                ${fieldValue(bean:costCodeInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/costCodeDetailed/show/${costCodeInstance.id}"'>
+                                ${fieldValue(bean:costCodeInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/costCodeDetailed/show/${costCodeInstance.id}"'>
+                                ${fieldValue(bean:costCodeInstance, field:'purchasingGroup')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/costCodeDetailed/show/${costCodeInstance.id}"'>
+                                ${fieldValue(bean:costCodeInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/costCodeDetailed/show/${costCodeInstance.id}"'>
+                                ${fieldValue(bean:costCodeInstance, field:'isActive')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${costCodeInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${costCodeInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/costCodeDetailed/show.gsp	(revision 753)
@@ -0,0 +1,70 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show CostCode</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:costCodeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:costCodeInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Purchasing Group:</td>
+                            <td valign="top" class="value">
+                                <g:link controller="purchasingGroupDetailed" action="show" id="${costCodeInstance?.purchasingGroup?.id}">
+                                    ${costCodeInstance?.purchasingGroup?.encodeAsHTML()}
+                                </g:link>
+                            </td>
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:costCodeInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:costCodeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${costCodeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/departmentDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/departmentDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/departmentDetailed/create.gsp	(revision 753)
@@ -0,0 +1,71 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Department</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${departmentInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${departmentInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:departmentInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:departmentInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:departmentInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${departmentInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/departmentDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/departmentDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/departmentDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,123 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit Department</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${departmentInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${departmentInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${departmentInstance?.id}" />
+                <input type="hidden" name="version" value="${departmentInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:departmentInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:departmentInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:departmentInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${departmentInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="departmentExtendedAttributes">Department Extended Attributes:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'departmentExtendedAttributes','errors')}">
+                                    
+<ul>
+<g:each var="d" in="${departmentInstance?.departmentExtendedAttributes?}">
+    <li><g:link controller="departmentExtendedAttributeDetailed" action="show" id="${d.id}">${d?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="departmentExtendedAttributeDetailed" params="['department.id':departmentInstance?.id]" action="create">+Add Extended Attribute</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="persons">Persons:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'persons','errors')}">
+                                    
+<ul>
+<g:each var="p" in="${departmentInstance?.persons?}">
+    <li><g:link controller="person" action="show" id="${p.id}">${p?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="person" params="['department.id':departmentInstance?.id]" action="create">+Add Person</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="sections">Sections:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentInstance,field:'sections','errors')}">
+                                    
+<ul>
+<g:each var="s" in="${departmentInstance?.sections?}">
+    <li><g:link controller="sectionDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="sectionDetailed" params="['department.id':departmentInstance?.id]" action="create">+Add Section</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/departmentDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/departmentDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/departmentDetailed/list.gsp	(revision 753)
@@ -0,0 +1,69 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Department List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${departmentInstanceList}" status="i" var="departmentInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/departmentDetailed/show/${departmentInstance.id}"'>
+                                ${fieldValue(bean:departmentInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/departmentDetailed/show/${departmentInstance.id}"'>
+                                ${fieldValue(bean:departmentInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/departmentDetailed/show/${departmentInstance.id}"'>
+                                ${fieldValue(bean:departmentInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/departmentDetailed/show/${departmentInstance.id}"'>
+                                ${fieldValue(bean:departmentInstance, field:'isActive')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${departmentInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${departmentInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/departmentDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/departmentDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/departmentDetailed/show.gsp	(revision 753)
@@ -0,0 +1,107 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show Department</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:departmentInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:departmentInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:departmentInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Comment:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:departmentInstance, field:'comment')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:departmentInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Department Extended Attributes:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="d" in="${departmentInstance.departmentExtendedAttributes}">
+                                    <li><g:link controller="departmentExtendedAttributeDetailed" action="show" id="${d.id}">${d?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Persons:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="p" in="${departmentInstance.persons}">
+                                    <li><g:link controller="person" action="show" id="${p.id}">${p?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Sections:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="s" in="${departmentInstance.sections}">
+                                    <li><g:link controller="sectionDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${departmentInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/departmentExtendedAttributeDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/departmentExtendedAttributeDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/departmentExtendedAttributeDetailed/create.gsp	(revision 753)
@@ -0,0 +1,70 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create DepartmentExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Department Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${departmentExtendedAttributeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${departmentExtendedAttributeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="value">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentExtendedAttributeInstance,field:'value','errors')}">
+                                    <input type="text" maxlength="100" id="value" name="value" value="${fieldValue(bean:departmentExtendedAttributeInstance,field:'value')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentExtendedAttributeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${departmentExtendedAttributeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="department">Department:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentExtendedAttributeInstance,field:'department','errors')}">
+                                    <g:select optionKey="id" from="${Department.list()}" name="department.id" value="${departmentExtendedAttributeInstance?.department?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="extendedAttributeType">Extended Attribute Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentExtendedAttributeInstance,field:'extendedAttributeType','errors')}">
+                                    <g:select optionKey="id" from="${ExtendedAttributeType.list()}" name="extendedAttributeType.id" value="${departmentExtendedAttributeInstance?.extendedAttributeType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/departmentExtendedAttributeDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/departmentExtendedAttributeDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/departmentExtendedAttributeDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,74 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit DepartmentExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Department Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${departmentExtendedAttributeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${departmentExtendedAttributeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${departmentExtendedAttributeInstance?.id}" />
+                <input type="hidden" name="version" value="${departmentExtendedAttributeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="value">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentExtendedAttributeInstance,field:'value','errors')}">
+                                    <input type="text" maxlength="100" id="value" name="value" value="${fieldValue(bean:departmentExtendedAttributeInstance,field:'value')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentExtendedAttributeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${departmentExtendedAttributeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="department">Department:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentExtendedAttributeInstance,field:'department','errors')}">
+                                    <g:select optionKey="id" from="${Department.list()}" name="department.id" value="${departmentExtendedAttributeInstance?.department?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="extendedAttributeType">Extended Attribute Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:departmentExtendedAttributeInstance,field:'extendedAttributeType','errors')}">
+                                    <g:select optionKey="id" from="${ExtendedAttributeType.list()}" name="extendedAttributeType.id" value="${departmentExtendedAttributeInstance?.extendedAttributeType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/departmentExtendedAttributeDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/departmentExtendedAttributeDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/departmentExtendedAttributeDetailed/show.gsp	(revision 753)
@@ -0,0 +1,67 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show DepartmentExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Department Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:departmentExtendedAttributeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Value:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:departmentExtendedAttributeInstance, field:'value')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:departmentExtendedAttributeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Department:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="departmentDetailed" action="show" id="${departmentExtendedAttributeInstance?.department?.id}">${departmentExtendedAttributeInstance?.department?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Extended Attribute Type:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="extendedAttributeTypeDetailed" action="show" id="${departmentExtendedAttributeInstance?.extendedAttributeType?.id}">${departmentExtendedAttributeInstance?.extendedAttributeType?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${departmentExtendedAttributeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/entryDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/entryDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/entryDetailed/create.gsp	(revision 753)
@@ -0,0 +1,113 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Entry</title>
+        <nav:resources override="true"/>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Entry</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${entryInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${entryInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <g:hiddenField name="task.id" value="${entryInstance.task.id}" />
+                <g:hiddenField name="entryType.id" value="${entryInstance.entryType.id}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="task">Task:</label>
+                                </td>
+                                <td valign="top" class="name">
+                                    <g:link controller="taskDetailed" action="show" id="${entryInstance.task.id}" >
+                                        ${entryInstance?.task.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">${entryInstance?.entryType.encodeAsHTML()}:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:entryInstance, field:'comment')}</textarea>
+                                    <g:if test="${entryInstance?.entryType?.id == 1}">
+                                        <g:helpBalloon code="entry.comment.fault" />
+                                    </g:if>
+                                    <g:elseif test="${entryInstance?.entryType?.id == 2}">
+                                        <g:helpBalloon code="entry.comment.cause" />
+                                    </g:elseif>
+                                    <g:elseif test="${entryInstance?.entryType?.id == 3}">
+                                        <g:helpBalloon code="entry.comment.work.done" />
+                                    </g:elseif>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="dateDone">Date Done:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryInstance,field:'dateDone','errors')}">
+                                    <richui:dateChooser name="dateDone" format="dd-MM-yyyy" value="${entryInstance.dateDone}" />
+                                    <g:helpBalloon code="entry.date.done" />
+                                </td>
+                            </tr>
+
+                            <g:if test="${entryInstance?.entryType?.id == 1}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="productionReference">Production:</label>
+                                    </td>
+                                    <td valign="top" class="value ${hasErrors(bean:entryInstance,field:'productionReference','errors')}">
+                                        <g:select optionKey="id"
+                                                            from="${ProductionReference.findAllByIsActive(true)}"
+                                                            name="productionReference.id"
+                                                            value="${entryInstance.productionReference?.id}"
+                                                            noSelection="['null':'--None--']">
+                                        </g:select>
+                                        <g:helpBalloon code="entry.productionReference.fault" />
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                            <g:if test="${entryInstance?.entryType?.id != 2}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="durationHour">Duration:</label>
+                                    </td>
+
+                                    <td valign="top" class="value">
+                                        <input class="time ${hasErrors(bean:entryInstance,field:'durationHour','errors')}" 
+                                            type="text" id="durationHour" name="durationHour" 
+                                            value="${fieldValue(bean:entryInstance,field:'durationHour')}" />
+                                        :
+                                        <input class="time ${hasErrors(bean:entryInstance,field:'durationMinute','errors')}" 
+                                            type="text" id="durationMinute" name="durationMinute" 
+                                            value="${fieldValue(bean:entryInstance,field:'durationMinute')}" />
+                                        <g:helpBalloon code="entry.duration" />
+                                    </td>
+                                </tr>
+                            </g:if>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/entryDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/entryDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/entryDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,132 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit Entry</title>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Entry</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${entryInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${entryInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${entryInstance?.id}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="task">Task:</label>
+                                </td>
+                                <td valign="top" class="name">
+                                    <g:link controller="taskDetailed" action="show" id="${entryInstance.task.id}" >
+                                        ${entryInstance?.task.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:entryInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="dateDone">Date Done:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryInstance,field:'dateDone','errors')}">
+                                    <richui:dateChooser name="dateDone" format="dd-MM-yyyy" value="${entryInstance?.dateDone}" />
+                                </td>
+                            </tr>
+
+                            <g:if test="${entryInstance?.entryType?.id == 1}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="productionReference">Production:</label>
+                                    </td>
+                                    <td valign="top" class="value ${hasErrors(bean:entryInstance,field:'productionReference','errors')}">
+                                        <g:select optionKey="id"
+                                                            from="${ProductionReference.findAllByIsActive(true)}"
+                                                            name="productionReference.id"
+                                                            value="${entryInstance.productionReference?.id}"
+                                                            noSelection="['null':'--None--']">
+                                        </g:select>
+                                        <g:helpBalloon code="entry.productionReference.fault" />
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                            <g:if test="${entryInstance?.entryType?.id != 2}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="durationHour">Duration:</label>
+                                    </td>
+
+                                    <td valign="top" class="value">
+                                        <input class="time ${hasErrors(bean:entryInstance,field:'durationHour','errors')}" 
+                                            type="text" id="durationHour" name="durationHour" 
+                                            value="${fieldValue(bean:entryInstance,field:'durationHour')}" />
+                                        :
+                                        <input class="time ${hasErrors(bean:entryInstance,field:'durationMinute','errors')}" 
+                                            type="text" id="durationMinute" name="durationMinute" 
+                                            value="${fieldValue(bean:entryInstance,field:'durationMinute')}" />
+                                        <g:helpBalloon code="entry.duration" />
+                                    </td>
+                                </tr>
+                            </g:if>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="dateEntered">Date Entered:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:formatDate date="${entryInstance?.dateEntered}" format="EEE, dd-MMM-yyyy @ HH:mm"/>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="enteredBy">Entered By:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    ${entryInstance?.enteredBy?.toString()}
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="entryType">Entry Type:</label>
+                                </td>
+                                <td valign="top" class="name">
+                                        ${entryInstance?.entryType.encodeAsHTML()}
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/entryDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/entryDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/entryDetailed/show.gsp	(revision 753)
@@ -0,0 +1,103 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show Entry</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Entry</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:entryInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Task:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="taskDetailed" action="show" id="${entryInstance?.task?.id}">${entryInstance?.task?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Comment:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:entryInstance, field:'comment')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Date Done:</td>
+                            
+                            <td valign="top" class="value">
+                                <g:formatDate date="${entryInstance.dateDone}" format="EEE, dd-MMM-yyyy"/>
+                            </td>
+                            
+                        </tr>
+
+                        <g:if test="${entryInstance.productionReference}">
+                            <tr class="prop">
+                                <td valign="top" class="name">Production:</td>
+
+                                <td valign="top" class="value">
+                                    ${fieldValue(bean:entryInstance, field:'productionReference')}
+                                </td>
+
+                            </tr>
+                        </g:if>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Duration:</td>
+                            <td valign="top" class="value">${entryInstance.durationHour}h : ${entryInstance.durationMinute}min</td>
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Date Entered:</td>
+                            
+                            <td valign="top" class="value">
+                                <g:formatDate date="${entryInstance.dateEntered}" format="EEE, dd-MMM-yyyy @ HH:mm"/>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Entered By:</td>
+                            
+                            <td valign="top" class="value">${entryInstance?.enteredBy?.encodeAsHTML()}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Entry Type:</td>
+                            
+                            <td valign="top" class="value">${entryInstance?.entryType?.encodeAsHTML()}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${entryInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/entryType/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/entryType/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/entryType/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create EntryType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">EntryType List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create EntryType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${entryTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${entryTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryTypeInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:entryTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${entryTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryTypeInstance,field:'name','errors')}">
+                                    <input type="text" id="name" name="name" value="${fieldValue(bean:entryTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/entryType/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/entryType/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/entryType/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit EntryType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">EntryType List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New EntryType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit EntryType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${entryTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${entryTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${entryTypeInstance?.id}" />
+                <input type="hidden" name="version" value="${entryTypeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryTypeInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:entryTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="entries">Entries:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryTypeInstance,field:'entries','errors')}">
+                                    
+<ul>
+<g:each var="e" in="${entryTypeInstance?.entries?}">
+    <li><g:link controller="entry" action="show" id="${e.id}">${e?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="entry" params="['entryType.id':entryTypeInstance?.id]" action="create">Add Entry</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${entryTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryTypeInstance,field:'name','errors')}">
+                                    <input type="text" id="name" name="name" value="${fieldValue(bean:entryTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/entryType/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/entryType/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/entryType/list.gsp	(revision 753)
@@ -0,0 +1,55 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>EntryType List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New EntryType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>EntryType List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${entryTypeInstanceList}" status="i" var="entryTypeInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${entryTypeInstance.id}">${fieldValue(bean:entryTypeInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:entryTypeInstance, field:'description')}</td>
+                        
+                            <td>${fieldValue(bean:entryTypeInstance, field:'isActive')}</td>
+                        
+                            <td>${fieldValue(bean:entryTypeInstance, field:'name')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${entryTypeInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/entryType/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/entryType/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/entryType/show.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show EntryType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">EntryType List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New EntryType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show EntryType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:entryTypeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:entryTypeInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Entries:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="e" in="${entryTypeInstance.entries}">
+                                    <li><g:link controller="entry" action="show" id="${e.id}">${e?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:entryTypeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:entryTypeInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${entryTypeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/error.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/error.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/error.gsp	(revision 753)
@@ -0,0 +1,54 @@
+<html>
+  <head>
+	  <title>Grails Runtime Exception</title>
+	  <style type="text/css">
+	  		.message {
+	  			border: 1px solid black;
+	  			padding: 5px;
+	  			background-color:#E9E9E9;
+	  		}
+	  		.stack {
+	  			border: 1px solid black;
+	  			padding: 5px;
+	  			overflow:auto;
+	  			height: 300px;
+	  		}
+	  		.snippet {
+	  			padding: 5px;
+	  			background-color:white;
+	  			border:1px solid black;
+	  			margin:3px;
+	  			font-family:courier;
+	  		}
+	  </style>
+  </head>
+
+  <body>
+    <h1>Grails Runtime Exception</h1>
+    <h2>Error Details</h2>
+
+  	<div class="message">
+		<strong>Error ${request.'javax.servlet.error.status_code'}:</strong> ${request.'javax.servlet.error.message'.encodeAsHTML()}<br/>
+		<strong>Servlet:</strong> ${request.'javax.servlet.error.servlet_name'}<br/>
+		<strong>URI:</strong> ${request.'javax.servlet.error.request_uri'}<br/>
+		<g:if test="${exception}">
+	  		<strong>Exception Message:</strong> ${exception.message?.encodeAsHTML()} <br />
+	  		<strong>Caused by:</strong> ${exception.cause?.message?.encodeAsHTML()} <br />
+	  		<strong>Class:</strong> ${exception.className} <br />
+	  		<strong>At Line:</strong> [${exception.lineNumber}] <br />
+	  		<strong>Code Snippet:</strong><br />
+	  		<div class="snippet">
+	  			<g:each var="cs" in="${exception.codeSnippet}">
+	  				${cs?.encodeAsHTML()}<br />
+	  			</g:each>
+	  		</div>
+		</g:if>
+  	</div>
+	<g:if test="${exception}">
+	    <h2>Stack Trace</h2>
+	    <div class="stack">
+	      <pre><g:each in="${exception.stackTraceLines}">${it.encodeAsHTML()}<br/></g:each></pre>
+	    </div>
+	</g:if>
+  </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create ExtendedAttributeType</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${extendedAttributeTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${extendedAttributeTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:extendedAttributeTypeInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:extendedAttributeTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:extendedAttributeTypeInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:extendedAttributeTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:extendedAttributeTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${extendedAttributeTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,68 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit ExtendedAttributeType</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${extendedAttributeTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${extendedAttributeTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${extendedAttributeTypeInstance?.id}" />
+                <input type="hidden" name="version" value="${extendedAttributeTypeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:extendedAttributeTypeInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:extendedAttributeTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:extendedAttributeTypeInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:extendedAttributeTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:extendedAttributeTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${extendedAttributeTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/list.gsp	(revision 753)
@@ -0,0 +1,71 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>ExtendedAttributeType List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                            <g:sortableColumn property="id" title="Id" />
+
+                            <g:sortableColumn property="name" title="Name" />
+
+                            <g:sortableColumn property="description" title="Description" />
+
+                            <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${extendedAttributeTypeInstanceList}" status="i" var="extendedAttributeTypeInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/extendedAttributeTypeDetailed/show/${extendedAttributeTypeInstance.id}"'>
+                                ${fieldValue(bean:extendedAttributeTypeInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/extendedAttributeTypeDetailed/show/${extendedAttributeTypeInstance.id}"'>
+                                ${fieldValue(bean:extendedAttributeTypeInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/extendedAttributeTypeDetailed/show/${extendedAttributeTypeInstance.id}"'>
+                                ${fieldValue(bean:extendedAttributeTypeInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/extendedAttributeTypeDetailed/show/${extendedAttributeTypeInstance.id}"'>
+                                ${fieldValue(bean:extendedAttributeTypeInstance, field:'isActive')}
+                            </td>
+                            
+                            <td class="notClickable">
+                                <g:link action="show" id="${extendedAttributeTypeInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${extendedAttributeTypeInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/extendedAttributeTypeDetailed/show.gsp	(revision 753)
@@ -0,0 +1,63 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show ExtendedAttributeType</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:extendedAttributeTypeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:extendedAttributeTypeInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:extendedAttributeTypeInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:extendedAttributeTypeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${extendedAttributeTypeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/index.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/index.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/index.gsp	(revision 753)
@@ -0,0 +1,1 @@
+<%response.sendRedirect(request.getContextPath()+'/appCore/')%>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create InventoryGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryGroupInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryGroupInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryGroupInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:inventoryGroupInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryGroupInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:inventoryGroupInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryGroupInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryGroupInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit InventoryGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryGroupInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryGroupInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${inventoryGroupInstance?.id}" />
+                <input type="hidden" name="version" value="${inventoryGroupInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryGroupInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:inventoryGroupInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryGroupInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:inventoryGroupInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryGroupInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryGroupInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryItems">Inventory Items:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryGroupInstance,field:'inventoryItems','errors')}">
+                                    
+<ul>
+<g:each var="i" in="${inventoryGroupInstance?.inventoryItems?}">
+    <li><g:link controller="inventoryItemDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="inventoryItemDetailed" params="['inventoryGroup.id':inventoryGroupInstance?.id]" action="create">+Add Inventory Item</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/list.gsp	(revision 753)
@@ -0,0 +1,71 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>InventoryGroup List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                            <g:sortableColumn property="id" title="Id" />
+
+                            <g:sortableColumn property="name" title="Name" />
+
+                            <g:sortableColumn property="description" title="Description" />
+
+                            <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${inventoryGroupInstanceList}" status="i" var="inventoryGroupInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryGroupDetailed/show/${inventoryGroupInstance.id}"'>
+                                ${fieldValue(bean:inventoryGroupInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryGroupDetailed/show/${inventoryGroupInstance.id}"'>
+                                ${fieldValue(bean:inventoryGroupInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryGroupDetailed/show/${inventoryGroupInstance.id}"'>
+                                ${fieldValue(bean:inventoryGroupInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryGroupDetailed/show/${inventoryGroupInstance.id}"'>
+                                ${fieldValue(bean:inventoryGroupInstance, field:'isActive')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${inventoryGroupInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${inventoryGroupInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryGroupDetailed/show.gsp	(revision 753)
@@ -0,0 +1,76 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show InventoryGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryGroupInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryGroupInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryGroupInstance, field:'description')}</td>
+                            
+                        </tr>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryGroupInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Inventory Items:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="i" in="${inventoryGroupInstance.inventoryItems}">
+                                    <li><g:link controller="inventoryItemDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${inventoryGroupInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/create.gsp	(revision 753)
@@ -0,0 +1,260 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create InventoryItem</title>    
+        <nav:resources override="true"/>     
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${inventoryItemInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryItemInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="name">Inventory Item</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:inventoryItemInstance,field:'name')}"/>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.name" />
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'description','errors')}">
+                                    <textarea rows="5" cols="40" name="description">${fieldValue(bean:inventoryItemInstance, field:'description')}</textarea>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.description" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:inventoryItemInstance, field:'comment')}</textarea>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.comment" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="unitOfMeasure">Unit Of Measure:</label>
+                                </td>
+                                <td valign="top">
+                                    <g:select optionKey="id"
+                                                        from="${UnitOfMeasure.findAllByIsActive(true)}"
+                                                        name="unitOfMeasure.id"
+                                                        value="${inventoryItemInstance?.unitOfMeasure?.id}" >
+                                    </g:select>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.unit.of.measure" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="inventoryLocation">Inventory Location:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'inventoryLocation','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${ InventoryLocation.findAllByIsActive(true).sort { p1, p2 -> p1.toString().compareToIgnoreCase(p2.toString()) } }"
+                                                        name="inventoryLocation.id" value="${inventoryItemInstance?.inventoryLocation?.id}"
+                                                        optionValue="${{it.name+ ' in ' + it.inventoryStore}}"
+                                                        noSelection="['null':/${g.message(code:'default.please.select.text')}/]" >
+                                    </g:select>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.inventory.location" />
+
+                                <p><g:link controller="inventoryLocationDetailed" action="create">+Add Location</g:link></p>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="inventoryGroup">Inventory Group:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'inventoryGroup','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${InventoryGroup.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="inventoryGroup.id"
+                                                        value="${inventoryItemInstance?.inventoryGroup?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.please.select.text')}/]" >
+                                    </g:select>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.inventory.group" />
+                                <p><g:link controller="inventoryGroupDetailed" action="create">+Add Group</g:link></p>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="inventoryType">Inventory Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'inventoryType','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${InventoryType.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="inventoryType.id"
+                                                        value="${inventoryItemInstance?.inventoryType?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.please.select.text')}/]" >
+                                    </g:select>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.inventory.type" />
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="name">Reorder Details</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="enableReorderListing">Enable Reorder Listing:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'enableReorderListing','errors')}">
+                                    <g:checkBox name="enableReorderListing" value="${inventoryItemInstance?.enableReorderListing}" ></g:checkBox>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.enable.reorder.listing" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="reorderPoint">Reorder Point:</label>
+                                </td>
+                                <td valign="top">
+                                    <input class="medium ${hasErrors(bean:inventoryItemInstance,field:'reorderPoint','errors')}"
+                                                    type="text" id="reorderPoint" name="reorderPoint"
+                                                    value="${fieldValue(bean:inventoryItemInstance,field:'reorderPoint')}" />
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.reorder.point" />
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="reorderQuantity">Reorder Quantity:</label>
+                                </td>
+                                <td valign="top">
+                                    <input class="medium ${hasErrors(bean:inventoryItemInstance,field:'reorderQuantity','errors')}"
+                                                type="text" id="reorderQuantity" name="reorderQuantity"
+                                                value="${fieldValue(bean:inventoryItemInstance,field:'reorderQuantity')}" />
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.reorder.quantity" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="estimatedUnitPriceAmount">Estimated Unit Price:</label>
+                                </td>
+                                <td valign="top">
+                                    <input  class="medium ${hasErrors(bean:inventoryItemInstance,field:'estimatedUnitPriceAmount','errors')}"
+                                                    type="text" id="estimatedUnitPriceAmount" name="estimatedUnitPriceAmount"
+                                                    value="${fieldValue(bean:inventoryItemInstance,field:'estimatedUnitPriceAmount')}" />
+                                    <g:currencySelect name="estimatedUnitPriceCurrency"
+                                                                        value="${inventoryItemInstance?.estimatedUnitPriceCurrency}"
+                                                                        from="${grailsApplication.config.currencyList}">
+                                    </g:currencySelect>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.estimated.unit.price.amount" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="suppliersPartNumber">Suppliers Part Number:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'suppliersPartNumber','errors')}">
+                                    <input type="text" id="suppliersPartNumber" maxlength="50" name="suppliersPartNumber" value="${fieldValue(bean:inventoryItemInstance,field:'suppliersPartNumber')}"/>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.suppliers.part.number" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="preferredSupplier">Preferred Supplier:</label>
+                                </td>
+                                <td valign="top">
+                                    <g:select optionKey="id"
+                                                        from="${suppliers}"
+                                                        name="preferredSupplier.id"
+                                                        value="${inventoryItemInstance.preferredSupplier?.id}"
+                                                        noSelection="['null':'--None--']">
+                                    </g:select>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.preferred.supplier" />
+                                    <p><g:link controller="supplierDetailed" action="create">+Add Supplier</g:link></p>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="alternateSuppliers">Alternate Suppliers:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'alternateSuppliers','errors')}">
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.alternate.suppliers" />
+                                    <custom:checkBoxList name="alternateSuppliers"
+                                                                    from="${suppliers}"
+                                                                    value="${inventoryItemInstance?.alternateSuppliers?.collect{it.id}}"
+                                                                    optionKey="id"
+                                                                    linkController="supplierDetailed"
+                                                                    linkAction="show"/>
+                                    <g:link controller="supplierDetailed" action="create">+Add Supplier</g:link>
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="name">Spare For</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="spareFor">Assets:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'spareFor','errors')}">
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.spare.for" />
+                                    <custom:checkBoxList name="spareFor"
+                                                                    from="${Asset.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                                    value="${inventoryItemInstance?.spareFor?.collect{it.id}}"
+                                                                    optionKey="id"
+                                                                    sortBy="name"
+                                                                    linkController="assetDetailed"
+                                                                    linkAction="show"/>
+                                    <g:link controller="assetDetailed" action="create">+Add Asset</g:link>
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,298 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit InventoryItem</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${inventoryItemInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryItemInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${inventoryItemInstance?.id}" />
+                <input type="hidden" name="version" value="${inventoryItemInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label>Inventory Item</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'name','errors')}">
+                                    <input type="text"
+                                                class="description"
+                                                maxlength="50"
+                                                id="name"
+                                                name="name"
+                                                value="${fieldValue(bean:inventoryItemInstance,field:'name')}"/>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.name" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">Picture:</td>
+                                <td valign="top" class="value">
+                                    <g:if test="${inventoryItemInstance.picture}" >
+                                        <span class='gallery'>
+                                            <wa:pictureLightboxAnchor picture="${inventoryItemInstance.picture}" size="${Image.Small}" lightboxSize="${Image.Large}" target="_blank" title="Show Original" />
+                                        </span>
+                                        <br />
+                                        <g:link controller="pictureDetailed" action="edit" id="${inventoryItemInstance.picture.id}" >
+                                            Edit Picture
+                                        </g:link>
+                                    </g:if>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'description','errors')}">
+                                    <textarea rows="5" cols="40" name="description">${fieldValue(bean:inventoryItemInstance, field:'description')}</textarea>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.description" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:inventoryItemInstance, field:'comment')}</textarea>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.comment" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="unitsInStock">In Stock:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    ${inventoryItemInstance.unitsInStock} ${inventoryItemInstance.unitOfMeasure.encodeAsHTML()}
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.units.in.stock" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="inventoryLocation">Location:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'inventoryLocation','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${ InventoryLocation.findAllByIsActive(true).sort { p1, p2 -> p1.toString().compareToIgnoreCase(p2.toString()) } }"
+                                                        name="inventoryLocation.id"
+                                                        value="${inventoryItemInstance?.inventoryLocation?.id}"
+                                                        optionValue="${{it.name+ ' in ' + it.inventoryStore}}">
+                                    </g:select>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.inventory.location" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="inventoryGroup">Inventory Group:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'inventoryGroup','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${InventoryGroup.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="inventoryGroup.id"
+                                                        value="${inventoryItemInstance?.inventoryGroup?.id}" >
+                                    </g:select>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.inventory.group" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="inventoryType">Inventory Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'inventoryType','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${InventoryType.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="inventoryType.id"
+                                                        value="${inventoryItemInstance?.inventoryType?.id}" >
+                                    </g:select>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.inventory.type" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="name">Reorder Details</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="isActive">Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryItemInstance?.isActive}" ></g:checkBox>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.is.active" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="isObsolete">Obsolete:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'isObsolete','errors')}">
+                                    <g:checkBox name="isObsolete" value="${inventoryItemInstance?.isObsolete}" ></g:checkBox>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.is.obsolete" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="enableReorderListing">Enable Reorder Listing:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'enableReorderListing','errors')}">
+                                    <g:checkBox name="enableReorderListing" value="${inventoryItemInstance?.enableReorderListing}" ></g:checkBox>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.enable.reorder.listing" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="reorderPoint">Reorder Point:</label>
+                                </td>
+                                <td valign="top">
+                                    <input  class="medium ${hasErrors(bean:inventoryItemInstance,field:'reorderPoint','errors')}"
+                                                    type="text" id="reorderPoint" name="reorderPoint"
+                                                    value="${fieldValue(bean:inventoryItemInstance,field:'reorderPoint')}" />
+                                    ${inventoryItemInstance.unitOfMeasure.encodeAsHTML()}
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.reorder.point" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="reorderQuantity">Reorder Quantity:</label>
+                                </td>
+                                <td valign="top">
+                                    <input class="medium ${hasErrors(bean:inventoryItemInstance,field:'reorderQuantity','errors')}"
+                                                type="text" id="reorderQuantity" name="reorderQuantity"
+                                                value="${fieldValue(bean:inventoryItemInstance,field:'reorderQuantity')}" />
+                                     ${inventoryItemInstance.unitOfMeasure.encodeAsHTML()}
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.reorder.quantity" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="estimatedUnitPriceAmount">Estimated Unit Price:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <input  class="medium ${hasErrors(bean:inventoryItemInstance,field:'estimatedUnitPriceAmount','errors')}"
+                                                    type="text" id="estimatedUnitPriceAmount" name="estimatedUnitPriceAmount"
+                                                    value="${inventoryItemInstance.estimatedUnitPriceAmount}" />
+                                    <g:currencySelect name="estimatedUnitPriceCurrency"
+                                                                        value="${inventoryItemInstance?.estimatedUnitPriceCurrency}"
+                                                                        from="${grailsApplication.config.currencyList}">
+                                    </g:currencySelect>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.estimated.unit.price.amount" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="suppliersPartNumber">Suppliers Part Number:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'suppliersPartNumber','errors')}">
+                                    <input type="text" id="suppliersPartNumber" maxlength="50" name="suppliersPartNumber" value="${fieldValue(bean:inventoryItemInstance,field:'suppliersPartNumber')}"/>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.suppliers.part.number" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="preferredSupplier">Preferred Supplier:</label>
+                                </td>
+                                <td valign="top">
+                                    <g:select optionKey="id"
+                                                    from="${suppliers}"
+                                                    name="preferredSupplier.id"
+                                                    value="${inventoryItemInstance.preferredSupplier?.id}"
+                                                    noSelection="['null':'--None--']">
+                                    </g:select>
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.preferred.supplier" />
+                                    <p><g:link controller="supplierDetailed" action="create">+Add Supplier</g:link></p>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="alternateSuppliers">Alternate Suppliers:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'alternateSuppliers','errors')}">
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.alternate.suppliers" />
+                                    <custom:checkBoxList name="alternateSuppliers"
+                                                                    from="${suppliers}"
+                                                                    value="${inventoryItemInstance?.alternateSuppliers?.collect{it.id}}"
+                                                                    optionKey="id"
+                                                                    linkController="supplierDetailed"
+                                                                    linkAction="show"/>
+                                    <g:link controller="supplierDetailed" action="create">+Add Supplier</g:link>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupHeader">
+                                    <label for="name">Spare For</label>
+                                </td>
+                                <td valign="top" class="value">
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="groupName">
+                                    <label for="spareFor">Assets:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemInstance,field:'spareFor','errors')}">
+                                    <g:helpBalloon class="helpballoon" code="inventory.item.spare.for" />
+                                    <custom:checkBoxList name="spareFor"
+                                                                    from="${Asset.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                                    value="${inventoryItemInstance?.spareFor?.collect{it.id}}"
+                                                                    optionKey="id"
+                                                                    sortBy="name"
+                                                                    linkController="assetDetailed"
+                                                                    linkAction="show"/>
+                                    <g:link controller="assetDetailed" action="create">+Add Asset</g:link>
+                                </td>
+                            </tr>
+
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/importInventory.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/importInventory.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/importInventory.gsp	(revision 753)
@@ -0,0 +1,35 @@
+<html>
+    <head>
+        <meta name="layout" content="main" />
+        <title>Import Inventory</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Import Inventory</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:uploadForm action="importInventorySave" onsubmit="return Lightbox.loading();">
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="file">File:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <input type="file" id="file" name="file" size="40"/>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:uploadForm>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/importInventoryItemPictures.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/importInventoryItemPictures.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/importInventoryItemPictures.gsp	(revision 753)
@@ -0,0 +1,36 @@
+<html>
+    <head>
+        <meta name="layout" content="main" />
+        <title>Import Inventory</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Import Inventory Pictures</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:uploadForm action="importInventoryItemPicturesSave" onsubmit="return Lightbox.loading();">
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="file">File:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <input type="file" id="file" name="file" size="40"/>
+                                    <g:helpBalloon code="inventoryItemPictures.import" />
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:uploadForm>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/importInventoryItemPurchases.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/importInventoryItemPurchases.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/importInventoryItemPurchases.gsp	(revision 753)
@@ -0,0 +1,35 @@
+<html>
+    <head>
+        <meta name="layout" content="main" />
+        <title>Import Inventory Item Purchases</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Import Inventory Purchases</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:uploadForm action="importInventoryItemPurchasesSave" onsubmit="return Lightbox.loading();">
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="file">File:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <input type="file" id="file" name="file" size="40"/>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:uploadForm>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/reorder.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/reorder.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/reorder.gsp	(revision 753)
@@ -0,0 +1,309 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>InventoryItem Reorder</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+        <filterpane:includes />
+        <export:resource />
+    </head>
+    <body onload="if(document.textSearchForm) {document.textSearchForm.searchText.focus();}">
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+
+            <div class="textSearchWrapper">
+                <div class="textSearchInput">
+
+                    <g:form method="post" id="textSearchForm" name="textSearchForm" >
+                        <g:hiddenField name="newSearch" value="true" />
+
+                            <span> <!--Prevent IE inheriting margin-->
+
+                                <table>
+                                    <tr>
+                                        <td>
+                                            <label for="selectedGroups">
+                                                Group:
+                                            </label>
+                                        </td>
+                                        <td>
+                                            <custom:checkBoxList name="selectedGroups"
+                                                                            from="${inventoryGroups}"
+                                                                            value="${params.selectedGroups}"
+                                                                            optionKey="id"
+                                                                            sortBy="name"
+                                                                            height="120px"/>
+                                        </td>
+                                    </tr>
+                                    <tr>
+                                        <td>
+                                            <label for="selectedSupplier">
+                                                Supplier:
+                                            </label>
+                                        </td>
+                                        <td>
+                                            <g:select optionKey="id"
+                                                                from="${suppliers}"
+                                                                name="selectedSupplier"
+                                                                value="${params.selectedSupplier}"
+                                                                noSelection="['null':'--None--']">
+                                            </g:select>
+                                        </td>
+                                    </tr>
+                                    <tr>
+                                        <td>
+                                        </td>
+                                        <td>
+                                            <g:checkBox name="includeAlternateSuppliers" value="${params.includeAlternateSuppliers}" >
+                                            </g:checkBox>
+                                            <label for="includeAlternateSuppliers">
+                                                Include alternate suppliers
+                                            </label>
+                                        </td>
+                                    </tr>
+                                    <tr>
+                                        <td>
+                                        </td>
+                                        <td>
+                                            <g:checkBox name="includeReorderListingDisabled" value="${params.includeReorderListingDisabled}" >
+                                            </g:checkBox>
+                                            <label for="includeReorderListingDisabled">
+                                                Include reorder listing disabled
+                                            </label>
+                                        </td>
+                                    </tr>
+                                    <tr>
+                                        <td>
+                                        </td>
+                                        <td>
+                                            <g:checkBox name="includeOnBackOrder" value="${params.includeOnBackOrder}" >
+                                            </g:checkBox>
+                                            <label for="includeOnBackOrder">
+                                                Include items ordered in last 30 days.
+                                            </label>
+                                        </td>
+                                    </tr>
+                                </table>
+
+                                <div class="paginateButtons">
+                                    <span class="buttons">
+                                        <g:actionSubmit class="search" value="Search" action="reorder" />
+                                    </span>
+                                    <div class="paginateButtons">
+                                        Results: ${inventoryItemInstanceList.size()} / ${inventoryItemInstanceTotal}
+                                    </div>
+                                </div><!--paginateButtons-->
+                            </span> <!--Prevent IE inheriting margin-->
+
+                    </g:form>
+
+                </div><!--textSearchInput-->
+
+                <div class="textSearchRightFloat">
+                    <div class="paginateButtons">
+                        <span class="searchButtons">
+                            <a href='' onclick="showElement('searchPane'); return false;">Quick</a>
+                        </span>
+                        <br />
+                        <br />
+                    </div>
+
+                    <jsUtil:toggleControl toggleId="options"
+                                                            imageId="optionsImg"
+                                                            closedImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_right.png')}"
+                                                            openImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_down.png')}"
+                                                            text="${g.message(code: 'default.options.text')}"
+                                                            />
+                </div><!--textSearchRightFloat-->
+            </div><!--textSearchWrapper-->
+
+            <div id="options" style="display:none; clear:both;">
+                <g:form method="post" action="setReorderSearchParamsMax" >
+                    <g:hiddenField name="params" value="${filterParams}" />
+                    <div class="dialog">
+                        <table>
+                            <tbody>
+
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="max">Results per page:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <input type="text" maxlength="4" id="description" name="newMax" value="${params.max}"/>
+
+                                        <span class="buttons">
+                                            <g:actionSubmit action="setReorderSearchParamsMax" class="go" value="Update" />
+                                        </span>
+                                    </td>
+                                </tr>
+
+                            </tbody>
+                        </table>
+                    </div>
+                </g:form>
+                <export:formats  params="${filterParams}" formats="['csv', 'excel', 'pdf', 'rtf']"/>
+            </div>
+
+            <br />
+
+            <g:if test="${inventoryItemInstanceList.size() > 2}">
+                <g:if test="${inventoryItemInstanceTotal > inventoryItemInstanceList.size()}">
+                    <div class="paginateButtons">
+                        <g:paginate action="reorder" total="${inventoryItemInstanceTotal}" params="${filterParams}" />
+                    </div>
+                </g:if>
+            </g:if>
+
+            <g:if test="${inventoryItemInstanceList.size() > 0}">
+                <div class="list">
+                    <table>
+                        <thead>
+                            <tr>
+
+                                <th>Picture</th>
+                                <th>Description</th>
+                            
+                                <g:sortableColumn property="inventoryGroup" title="Group" params="${filterParams}" />
+                            
+                                <g:sortableColumn property="unitsInStock" title="In Stock" params="${filterParams}" />
+
+                                <th></th>
+                            
+                            </tr>
+                        </thead>
+                        <tbody>
+                        <g:each in="${inventoryItemInstanceList}" status="i" var="inventoryItemInstance">
+                            <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}" />
+
+                                <td class='notClickable'>
+                                    <g:if test="${inventoryItemInstance.picture}" >
+                                        <wa:pictureLightboxAnchor picture="${inventoryItemInstance.picture}"
+                                                                                            size="${Image.Small}"
+                                                                                            lightboxSize="${Image.Large}"
+                                                                                            target="_blank"
+                                                                                            title="Show Original" />
+                                    </g:if>
+                                </td>
+                            
+                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemDetailed/show/${inventoryItemInstance.id}"' >
+                                    <b>${fieldValue(bean:inventoryItemInstance, field:'name')}</b><br />
+                                    ${fieldValue(bean:inventoryItemInstance, field:'description')}
+                                    <br />
+                                    <br />
+                                    Comment:<br />
+                                    ${inventoryItemInstance.comment?.encodeAsHTML()}
+                                    <br />
+                                    <br />
+                                    Reorder Point: ${fieldValue(bean:inventoryItemInstance, field:'reorderPoint')}
+                                    ${fieldValue(bean:inventoryItemInstance, field:'unitOfMeasure')}
+                                    <br />
+                                    P.Supplier: ${fieldValue(bean:inventoryItemInstance, field:'preferredSupplier')}
+                                    <br />
+                                    Spare For: ${inventoryItemInstance.spareFor.join(', ').encodeAsHTML()}
+                                </td>
+                            
+                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemDetailed/show/${inventoryItemInstance.id}"' >
+                                    ${fieldValue(bean:inventoryItemInstance, field:'inventoryGroup')}
+                                </td>
+                            
+                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemDetailed/show/${inventoryItemInstance.id}"' >
+                                    ${fieldValue(bean:inventoryItemInstance, field:'unitsInStock')}
+                                    ${fieldValue(bean:inventoryItemInstance, field:'unitOfMeasure')}
+                                </td>
+
+                                <td class="notClickable">
+                                    <g:link action="show" id="${inventoryItemInstance.id}">
+                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                    </g:link>
+                                </td>
+                            
+                            </tr>
+                        </g:each>
+                        </tbody>
+                    </table>
+                </div>
+            </g:if>
+            <div class="paginateButtons">
+                <g:paginate action="reorder" total="${inventoryItemInstanceTotal}" params="${filterParams}" />
+            </div>
+
+        </div> <!-- end body div -->
+
+        <!-- Start Search Pane -->
+        <div class="overlayPane" id="searchPane" style="display:none;">
+            <h2>Quick Search</h2>
+
+            <g:form method="post" id="searchForm" name="searchForm" >
+                <g:hiddenField name="newTextSearch" value="true" />
+
+                <table>
+                    <tbody>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label>Inventory:</label>
+                            </td>
+                            <td valign="top" class="value">
+                                <g:link controller="inventoryItemDetailed"
+                                                action="reorder"
+                                                params="[quickSearch: 'all']">
+                                                <g:message code="default.all.text" />
+                                </g:link>
+                                <br />
+                                <g:link controller="inventoryItemDetailed"
+                                                action="reorder"
+                                                params="[quickSearch: 'inventoryBelowReorder']">
+                                                <g:message code="inventoryItem.search.text.below.reorder" />
+                                </g:link> - <g:message code="inventoryItem.search.text.below.reorder.description" />
+                                <br />
+                                <g:link controller="inventoryItemDetailed"
+                                                action="reorder"
+                                                params="[quickSearch: 'inventoryBelowReorderAll']">
+                                                <g:message code="inventoryItem.search.text.below.reorder.all" />
+                                </g:link> - <g:message code="inventoryItem.search.text.below.reorder.all.description" />
+                                <br />
+                                <g:link controller="inventoryItemDetailed"
+                                                action="reorder"
+                                                params="[quickSearch: 'recentlyUsed', daysBack: '14']">
+                                                <g:message code="inventoryItem.search.text.recently.used" />
+                                </g:link> - <g:message code="inventoryItem.search.text.recently.used.description" args="[14]"/>
+                                <br />
+                                <g:link controller="inventoryItemDetailed"
+                                                action="reorder"
+                                                params="[quickSearch: 'recentlyUsed', daysBack: '30']">
+                                                <g:message code="inventoryItem.search.text.recently.used" />
+                                </g:link> - <g:message code="inventoryItem.search.text.recently.used.description" args="[30]"/>
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label>Links:</label>
+                            </td>
+                            <td valign="top" class="value">
+                                <g:link controller="inventoryItemPurchaseDetailed"
+                                                action="search">
+                                                Purchases
+                                </g:link>
+                            </td>
+                        </tr>
+
+                    </tbody>
+                </table>
+
+                <div class="buttons">
+                    <span class="button">
+                        <g:actionSubmit class="cancel" value="${g.message(code:'fp.tag.filterPane.button.cancel.text', default:'Cancel')}" onclick="return hideElement('searchPane');" />
+                    </span>
+                </div>
+            </g:form>
+        </div> <!-- end search pane -->
+
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/search.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/search.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/search.gsp	(revision 753)
@@ -0,0 +1,327 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>InventoryItem Search</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+        <filterpane:includes />
+        <export:resource />
+    </head>
+    <body onload="if(document.textSearchForm) {document.textSearchForm.searchText.focus();}">
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+
+            <div class="textSearchWrapper">
+                <div class="textSearchInput">
+
+                    <filterpane:isFiltered >
+                        <filterpane:currentCriteria domainBean="InventoryItem"
+                                                action="search"
+                                                dateFormat="EEE, dd-MMM-yyyy"
+                                                removeImgDir="images"
+                                                removeImgFile="bullet_delete.png"
+                                                title="Advanced Search"/>
+                        <div class="paginateButtons">
+                            Results: ${inventoryItemInstanceList.size()} / ${inventoryItemInstanceTotal}
+                        </div>
+                    </filterpane:isFiltered >
+
+                    <filterpane:isNotFiltered >
+                        <g:form method="post" id="textSearchForm" name="textSearchForm" >
+                            <g:hiddenField name="newTextSearch" value="true" />
+
+                                <span> <!--Prevent IE inheriting margin-->
+                                    <g:textField style="width:450px;" maxlength="75" id="searchText" name="searchText" value="${filterParams.searchText}" />
+                                    <g:helpBalloon code="inventoryItem.search.searchText" />
+
+                                    <g:if test="${params.searchName || params.searchDescription || params.searchComment || params.searchLocation || params.searchGroup || params.searchSpareFor}" >
+                                        <div id="limitSearch" class="textSearchSelect">
+                                    </g:if>
+                                    <g:else>
+                                        <div id="limitSearch" class="textSearchSelect" style="display:none;">
+                                    </g:else>
+                                            Limit Search:
+                                            <br />
+                                            <g:checkBox name="searchName" value="${params.searchName}" ></g:checkBox>
+                                            <label for="searchName">Name</label>
+                                            <g:checkBox name="searchDescription" value="${params.searchDescription}" ></g:checkBox>
+                                            <label for="searchDescription">Description</label>
+                                            <g:checkBox name="searchComment" value="${params.searchComment}" ></g:checkBox>
+                                            <label for="searchComment">Comment</label>
+                                            <g:checkBox name="searchLocation" value="${params.searchLocation}" ></g:checkBox>
+                                            <label for="searchLocation">Location</label>
+                                            <g:checkBox name="searchGroup" value="${params.searchGroup}" ></g:checkBox>
+                                            <label for="searchGroup">Group</label>
+                                            <br />
+                                            <g:checkBox name="searchSpareFor" value="${params.searchSpareFor}" ></g:checkBox>
+                                            <label for="searchSpareFor">Spare For (Asset: Name, Description and Comment).</label>
+                                        </div>
+
+                                    <div class="paginateButtons">
+                                        <span class="buttons">
+                                            <g:actionSubmit class="search" value="Search" action="search" />
+                                        </span>
+                                        <span class="buttons" style="margin-left: 5px;">
+                                            <g:actionSubmit class="complete" value="Select" action="search" onclick="toggleWithEffectUtil('limitSearch'); return false;"/>
+                                        </span>
+                                        <div class="paginateButtons">
+                                            Results: ${inventoryItemInstanceList.size()} / ${inventoryItemInstanceTotal}
+                                        </div>
+                                    </div><!--paginateButtons-->
+                                </span> <!--Prevent IE inheriting margin-->
+
+                        </g:form>
+                    </filterpane:isNotFiltered >
+
+                </div><!--textSearchInput-->
+
+                <div class="textSearchRightFloat">
+                    <div class="paginateButtons">
+                        <span class="searchButtons">
+                            <a href='' onclick="showElement('searchPane'); return false;">Quick</a>
+                        </span>
+                        <br />
+                        <br />
+                        <span class="searchButtons">
+                            <filterpane:filterButton text="Advanced" appliedText="Advanced" />
+                        </span>
+                    </div>
+
+                    <jsUtil:toggleControl toggleId="options"
+                                                            imageId="optionsImg"
+                                                            closedImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_right.png')}"
+                                                            openImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_down.png')}"
+                                                            text="${g.message(code: 'default.options.text')}"
+                                                            />
+                </div><!--textSearchRightFloat-->
+            </div><!--textSearchWrapper-->
+
+            <div id="options" style="display:none; clear:both;">
+                <g:form method="post" action="setSearchParamsMax" >
+                    <g:hiddenField name="params" value="${filterParams}" />
+                    <div class="dialog">
+                        <table>
+                            <tbody>
+
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="max">Results per page:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <input type="text" maxlength="4" id="description" name="newMax" value="${params.max}"/>
+
+                                        <span class="buttons">
+                                            <g:actionSubmit action="setSearchParamsMax" class="go" value="Update" />
+                                        </span>
+                                    </td>
+                                </tr>
+
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="max">Inventory:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:link action="exportInventory">
+                                            Export
+                                        </g:link>
+                                        /
+                                        <g:link action="exportInventoryTemplate">
+                                            Template
+                                        </g:link>
+                                        /
+                                        <g:link action="exportInventoryExample">
+                                            Example
+                                        </g:link>
+                                        /
+                                        <g:link action="importInventory">
+                                            Import Inventory
+                                        </g:link>
+                                        /
+                                        <g:link action="importInventoryItemPurchases">
+                                            Import Purchases
+                                        </g:link>
+                                        /
+                                        <g:link action="importInventoryItemPictures">
+                                            Import Pictures
+                                        </g:link>
+                                    </td>
+                                </tr>
+
+                            </tbody>
+                        </table>
+                    </div>
+                </g:form>
+                <export:formats  params="${filterParams}" formats="['csv', 'excel', 'pdf', 'rtf']"/>
+            </div>
+
+            <br />
+
+            <g:if test="${inventoryItemInstanceList.size() > 2}">
+                <g:if test="${inventoryItemInstanceTotal > inventoryItemInstanceList.size()}">
+                    <div class="paginateButtons">
+                        <g:paginate action="search" total="${inventoryItemInstanceTotal}" params="${filterParams}" />
+                    </div>
+                </g:if>
+            </g:if>
+
+            <g:if test="${inventoryItemInstanceList.size() > 0}">
+                <div class="list">
+                    <table>
+                        <thead>
+                            <tr>
+
+                                <th>Picture</th>
+                                <th>Description</th>
+                            
+                                <g:sortableColumn property="inventoryGroup" title="Group" params="${filterParams}" />
+                            
+                                <g:sortableColumn property="unitsInStock" title="In Stock" params="${filterParams}" />
+
+                                <th></th>
+                            
+                            </tr>
+                        </thead>
+                        <tbody>
+                        <g:each in="${inventoryItemInstanceList}" status="i" var="inventoryItemInstance">
+                            <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}" />
+
+                                <td class='notClickable'>
+                                    <g:if test="${inventoryItemInstance.picture}" >
+                                        <wa:pictureLightboxAnchor picture="${inventoryItemInstance.picture}"
+                                                                                            size="${Image.Small}"
+                                                                                            lightboxSize="${Image.Large}"
+                                                                                            target="_blank"
+                                                                                            title="Show Original" />
+                                    </g:if>
+                                </td>
+                            
+                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemDetailed/show/${inventoryItemInstance.id}"' >
+                                    <b>${fieldValue(bean:inventoryItemInstance, field:'name')}</b><br />
+                                    ${fieldValue(bean:inventoryItemInstance, field:'description')}
+                                    <br />
+                                    <br />
+                                    Location: ${inventoryItemInstance.inventoryLocation?.encodeAsHTML()}
+                                    in ${inventoryItemInstance.inventoryLocation?.inventoryStore.encodeAsHTML()}<br />
+                                </td>
+                            
+                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemDetailed/show/${inventoryItemInstance.id}"' >
+                                    ${fieldValue(bean:inventoryItemInstance, field:'inventoryGroup')}
+                                </td>
+                            
+                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemDetailed/show/${inventoryItemInstance.id}"' >
+                                    ${fieldValue(bean:inventoryItemInstance, field:'unitsInStock')}
+                                    ${fieldValue(bean:inventoryItemInstance, field:'unitOfMeasure')}
+                                </td>
+
+                                <td class="notClickable">
+                                    <g:link action="show" id="${inventoryItemInstance.id}">
+                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                    </g:link>
+                                </td>
+                            
+                            </tr>
+                        </g:each>
+                        </tbody>
+                    </table>
+                </div>
+            </g:if>
+            <div class="paginateButtons">
+                <g:paginate action="search" total="${inventoryItemInstanceTotal}" params="${filterParams}" />
+            </div>
+
+            <filterpane:filterPane domainBean="InventoryItem"
+                                    title="Advanced Search"
+                                    action="search"
+                                    class="overlayPane"
+                                    excludeProperties="estimatedUnitPriceCurrency"
+                                    associatedProperties="inventoryLocation.name,
+                                                                            spareFor.name"
+                                    filterPropertyValues="${['inventoryLocation.name':[values: associatedPropertyValues.inventoryLocationList],
+                                                                                'spareFor.name':[values: associatedPropertyValues.assetList],
+                                                                                'preferredSupplier.name':[values: associatedPropertyValues.supplierList]
+                                                                                ]}"/>
+        </div> <!-- end body div -->
+
+        <!-- Start Search Pane -->
+        <div class="overlayPane" id="searchPane" style="display:none;">
+            <h2>Quick Search</h2>
+
+            <g:form method="post" id="searchForm" name="searchForm" >
+                <g:hiddenField name="newTextSearch" value="true" />
+
+                <table>
+                    <tbody>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label>Inventory:</label>
+                            </td>
+                            <td valign="top" class="value">
+                                <g:link controller="inventoryItemDetailed"
+                                                action="search"
+                                                params="[quickSearch: 'all']">
+                                                <g:message code="default.all.text" />
+                                </g:link>
+                                <br />
+                                <g:link controller="inventoryItemDetailed"
+                                                action="search"
+                                                params="[quickSearch: 'inventoryBelowReorder']">
+                                                <g:message code="inventoryItem.search.text.below.reorder" />
+                                </g:link> - <g:message code="inventoryItem.search.text.below.reorder.description" />
+                                <br />
+                                <g:link controller="inventoryItemDetailed"
+                                                action="search"
+                                                params="[quickSearch: 'inventoryBelowReorderAll']">
+                                                <g:message code="inventoryItem.search.text.below.reorder.all" />
+                                </g:link> - <g:message code="inventoryItem.search.text.below.reorder.all.description" />
+                                <br />
+                                <g:link controller="inventoryItemDetailed"
+                                                action="search"
+                                                params="[quickSearch: 'recentlyUsed', daysBack: '14']">
+                                                <g:message code="inventoryItem.search.text.recently.used" />
+                                </g:link> - <g:message code="inventoryItem.search.text.recently.used.description" args="[14]"/>
+                                <br />
+                                <g:link controller="inventoryItemDetailed"
+                                                action="search"
+                                                params="[quickSearch: 'recentlyUsed', daysBack: '30']">
+                                                <g:message code="inventoryItem.search.text.recently.used" />
+                                </g:link> - <g:message code="inventoryItem.search.text.recently.used.description" args="[30]"/>
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label>Links:</label>
+                            </td>
+                            <td valign="top" class="value">
+                                <g:link controller="inventoryItemPurchaseDetailed"
+                                                action="search">
+                                                Purchases
+                                </g:link>
+                                <br />
+                                <g:link controller="inventoryItemDetailed"
+                                                action="reorder">
+                                                Reorder
+                                </g:link>
+                            </td>
+                        </tr>
+
+                    </tbody>
+                </table>
+
+                <div class="buttons">
+                    <span class="button">
+                        <g:actionSubmit class="cancel" value="${g.message(code:'fp.tag.filterPane.button.cancel.text', default:'Cancel')}" onclick="return hideElement('searchPane');" />
+                    </span>
+                </div>
+            </g:form>
+        </div> <!-- end search pane -->
+
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemDetailed/show.gsp	(revision 753)
@@ -0,0 +1,565 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show InventoryItem</title>
+        <nav:resources override="true"/>
+        <resource:tabView skin="tabviewCustom" />
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:if test="${inventoryItemInstance.isObsolete || !inventoryItemInstance.isActive}" >
+                <div class="errors">
+                    <ul>
+                        <g:if test="${inventoryItemInstance.isObsolete}" >
+                            <li><g:message code="inventory.item.is.obsolete.message" /><li>
+                        </g:if>
+                        <g:if test="${!inventoryItemInstance.isActive}" >
+                            <li><g:message code="inventory.item.not.active.message" /><li>
+                        </g:if>
+                    </ul>
+                </div>
+            </g:if>
+            <g:if test="${!inventoryItemInstance.enableReorderListing}" >
+                <div class="message">
+                    <g:message code="inventory.item.reorder.listing.disabled" />
+                </div>
+            </g:if>
+            <g:hasErrors bean="${inventoryMovementInstance}">
+                <div class="errors">
+                    <g:renderErrors bean="${inventoryMovementInstance}" as="list" />
+                </div>
+            </g:hasErrors>
+
+            <g:hasErrors bean="${inventoryItemInstance}">
+                <div class="errors">
+                    <g:renderErrors bean="${inventoryItemInstance}" as="list" />
+                </div>
+            </g:hasErrors>
+
+            <div class="tabHeader">
+                <h1>
+                    ${inventoryItemInstance.name}
+                </h1>
+                ${fieldValue(bean:inventoryItemInstance, field:'description')}
+            </div>
+
+            <br/>
+
+            <richui:tabView id="tabView">
+
+                <richui:tabLabels>
+                    <richui:tabLabel selected="${showTab.inventory}" title="Inventory Item" />
+                    <g:if test="${!inventoryMovementList.isEmpty()}">
+                        <richui:tabLabel selected="${showTab.movement}" title="Movement (${inventoryMovementList.size()})" />
+                    </g:if>
+                    <g:else>
+                        <richui:tabLabel selected="${showTab.movement}" title="Movement" />
+                    </g:else>
+                    <g:if test="${!inventoryItemPurchases.isEmpty()}">
+                        <richui:tabLabel selected="${showTab.purchasing}" title="Purchasing (${inventoryItemPurchases.size()})" />
+                    </g:if>
+                    <g:else>
+                        <richui:tabLabel selected="${showTab.purchasing}" title="Purchasing" />
+                    </g:else>
+                </richui:tabLabels>
+
+                <richui:tabContents>
+
+<!-- Start Inventory tab -->
+                    <richui:tabContent>
+
+                        <g:if test="${inventoryMovementInstance}" >
+
+                            <div id="useInventoryItemDiv" style="display:inline"> <!-- inline required for IE -->
+                                <div class="pane_close" >
+                                    <g:remoteLink action="clearUseInventoryItem" update="useInventoryItemDiv">
+                                        <img  src="${resource(dir:'images/skin',file:'cross.png')}" alt="Clear" title="Clear"/>
+                                    </g:remoteLink>
+                                </div>
+                                <g:form controller="inventoryItemDetailed" action="useInventoryItem" method="post" >
+                                    <div class="dialog">
+                                        <table>
+                                            <tbody>
+                                                    <g:hiddenField name="task.id" value="${inventoryMovementInstance.task.id}"/>
+                                                    <g:hiddenField name="inventoryItem.id" value="${inventoryItemInstance.id}"/>
+                                                    <tr class="prop">
+                                                        <td valign="top" class="name">Use on task:</td>
+                                                        <td valign="top" class="value">
+                                                            <g:link controller="taskDetailed" action="show" id="${inventoryMovementInstance.task.id}" >
+                                                                ${Task.get(inventoryMovementInstance.task.id).encodeAsHTML()}
+                                                            </g:link>
+                                                        </td>
+                                                    </tr>
+
+                                                    <tr class="prop">
+                                                        <td valign="top" class="name">
+                                                            <label for="quantity">Quantity:</label>
+                                                        </td>
+                                                        <td valign="top">
+                                                            <input class="medium ${hasErrors(bean:inventoryMovementInstance,field:'quantity','errors')}"
+                                                                        type="text" id="quantity" name="quantity"
+                                                                        value="${fieldValue(bean:inventoryMovementInstance,field:'quantity')}"/>
+                                                            ${inventoryItemInstance.unitOfMeasure?.encodeAsHTML()}
+
+                                                            <span class="buttons">
+                                                                <g:actionSubmit action="useInventoryItem" class="save" value="${InventoryMovementType.read(1)}" />
+                                                            </span>
+
+                                                        </td>
+                                                    </tr>
+
+                                            </tbody>
+                                        </table>
+                                    </div>
+                                </g:form>
+
+                                <br />
+                            </div>
+
+                        </g:if>
+
+                        <div class="dialog">
+                            <table>
+                                <tbody>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Picture:</td>
+                                        <td valign="top" class="value">
+                                            <g:if test="${inventoryItemInstance.picture}" >
+                                                <span class='gallery'><wa:pictureLightboxAnchor picture="${inventoryItemInstance.picture}" size="${Image.Small}" lightboxSize="${Image.Large}" target="_blank" title="Show Original" /></span>
+                                            </g:if>
+                                            <g:else>
+                                                <g:link controller="pictureDetailed"
+                                                                params="['inventoryItem.id':inventoryItemInstance.id]"
+                                                                action="create">
+                                                    Add Picture
+                                                </g:link>
+                                            </g:else>
+                                        </td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Comment:</td>
+
+                                        <td valign="top" class="value">${fieldValue(bean:inventoryItemInstance, field:'comment')}</td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">In Stock:</td>
+
+                                        <td valign="top" class="value">
+                                            ${fieldValue(bean:inventoryItemInstance, field:'unitsInStock')} ${inventoryItemInstance.unitOfMeasure.encodeAsHTML()}
+                                        </td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Location:</td>
+
+                                        <td valign="top" class="value">
+                                            <g:link controller="inventoryLocationDetailed" action="show" id="${inventoryItemInstance.inventoryLocation?.id}">
+                                                ${inventoryItemInstance.inventoryLocation?.encodeAsHTML()}
+                                            </g:link>
+                                                in ${inventoryItemInstance.inventoryLocation?.inventoryStore.encodeAsHTML()}
+                                        </td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Inventory Group:</td>
+                                        <td valign="top" class="value">${inventoryItemInstance.inventoryGroup?.encodeAsHTML()}</td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Inventory Type:</td>
+                                        <td valign="top" class="value">${inventoryItemInstance.inventoryType?.encodeAsHTML()}</td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupHeader">
+                                            <label for="name">Reorder Details</label>
+                                        </td>
+                                        <td valign="top" class="value">
+                                        </td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Active:</td>
+
+                                        <td valign="top" class="value">${fieldValue(bean:inventoryItemInstance, field:'isActive')}</td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Obsolete:</td>
+                                        <td valign="top" class="value">${fieldValue(bean:inventoryItemInstance, field:'isObsolete')}</td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Enable Reorder Listing:</td>
+                                        <td valign="top" class="value">${fieldValue(bean:inventoryItemInstance, field:'enableReorderListing')}</td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Reorder Point:</td>
+                                        <td valign="top" class="value">${fieldValue(bean:inventoryItemInstance, field:'reorderPoint')}</td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Reorder Quantity:</td>
+                                        <td valign="top" class="value">${fieldValue(bean:inventoryItemInstance, field:'reorderQuantity')}</td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Estimated Unit Price:</td>
+
+                                        <td valign="top" class="value">
+                                            <g:if test="${inventoryItemInstance.estimatedUnitPriceAmount}">
+                                                ${inventoryItemInstance.estimatedUnitPriceAmount.encodeAsHTML()}
+                                                ${inventoryItemInstance.estimatedUnitPriceCurrency.encodeAsHTML()}
+                                            </g:if>
+                                        </td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Suppliers Part Number:</td>
+                                        <td valign="top" class="value">${fieldValue(bean:inventoryItemInstance, field:'suppliersPartNumber')}</td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Preferred Supplier:</td>
+
+                                        <td  valign="top" style="text-align:left;" class="value">
+                                            <g:link controller="supplierDetailed" action="show" id="${inventoryItemInstance.preferredSupplier?.id}">
+                                                ${inventoryItemInstance.preferredSupplier?.encodeAsHTML()}
+                                            </g:link>
+                                        </td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Alternate Suppliers:</td>
+
+                                        <td  valign="top" style="text-align:left;" class="value">
+                                            <ul>
+                                            <g:each var="s" in="${ inventoryItemInstance.alternateSuppliers.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
+                                                <li><g:link controller="supplierDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+                                            </g:each>
+                                            </ul>
+                                        </td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupHeader">
+                                            <label for="name">Spare For</label>
+                                        </td>
+                                        <td valign="top" class="value">
+                                        </td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="groupName">Assets:</td>
+
+                                        <td  valign="top" style="text-align:left;" class="value">
+                                            <ul>
+                                            <g:each var="s" in="${ inventoryItemInstance.spareFor.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
+                                                <li><g:link controller="assetDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+                                            </g:each>
+                                            </ul>
+                                        </td>
+                                    </tr>
+
+                                </tbody>
+                            </table>
+                        </div>
+                        <div class="buttons">
+                            <g:form>
+                                <g:hiddenField name="id" value="${inventoryItemInstance.id}" />
+                                <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                                <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                            </g:form>
+                        </div>
+
+                        <br />
+
+                    </richui:tabContent>
+<!-- End Inventory tab -->
+
+<!-- Start Movement tab -->
+                    <richui:tabContent>
+
+                        <g:if test="${inventoryMovementList.isEmpty()}">
+                            <br />
+                            No Inventory Movements.
+                            <br />
+                            <br />
+
+                            <div class="buttons">
+                                <g:form controller="inventoryMovementDetailed">
+                                    <g:hiddenField name="inventoryItem.id" value="${inventoryItemInstance.id}" />
+                                    <span class="button"><g:actionSubmit action="create" class="add" value="Create" /></span>
+                                </g:form>
+                            </div>
+
+                        </g:if>
+                        <g:else>
+
+                            <div class="list">
+                                <table>
+                                    <thead>
+                                        <tr>
+                                            <th>Quantity</th>
+                                            <th>Movement Type</th>
+                                            <th>Date</th>
+                                            <th>Person</th>
+                                            <th></th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                        <g:each in="${inventoryMovementList}" status="i" var="movements">
+                                            <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${movements.id}"'>
+                                                    ${fieldValue(bean:movements, field:'quantity')}
+                                                </td>
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${movements.id}"'>
+                                                    ${fieldValue(bean:movements, field:'inventoryMovementType')}
+                                                </td>
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${movements.id}"'>
+                                                    <g:formatDate date="${movements.date}" format="EEE, dd-MMM-yyyy"/>
+                                                </td>
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${movements.id}"'>
+                                                    ${fieldValue(bean:movements, field:'person')}
+                                                </td>
+
+                                                <td class="notClickable">
+                                                    <g:link controller="inventoryMovementDetailed" action="show" id="${movements.id}">
+                                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                                    </g:link>
+                                                </td>
+
+                                            </tr>
+                                        </g:each>
+                                    </tbody>
+                                </table>
+                            </div>
+
+                            <div class="buttons">
+                                <g:form controller="inventoryMovementDetailed">
+                                    <g:hiddenField name="inventoryItem.id" value="${inventoryItemInstance.id}" />
+                                    <g:if test="${inventoryMovementListTotal > inventoryMovementListMax}">
+                                        Showing ${inventoryMovementListMax} of ${inventoryMovementListTotal}
+                                        <br />
+                                    </g:if>
+                                    <g:else>
+                                        Total ${inventoryMovementListTotal}
+                                        <br />
+                                    </g:else>
+                                    <span class="button"><g:actionSubmit action="listInventoryMovements" class="table" value="List" /></span>
+                                    <span class="button"><g:actionSubmit action="create" class="add" value="Create" /></span>
+                                </g:form>
+                            </div>
+
+                        </g:else>
+
+                    </richui:tabContent>
+<!-- End Movement tab -->
+
+<!-- Start Purchases tab -->
+                    <richui:tabContent>
+
+                        <g:if test="${inventoryItemPurchases.isEmpty()}">
+                            <br />
+                            No Inventory Purchases.
+                            <br />
+                            <br />
+
+                            <div class="buttons">
+                                <!--Fake button to prevent ordering disabled inventory items-->
+                                <g:if test="${inventoryItemInstance.isObsolete || !inventoryItemInstance.isActive}" >
+                                    <g:form controller="inventoryItemDetailed">
+                                        <g:hiddenField name="id" value="${inventoryItemInstance.id}" />
+                                        <span class="button">
+                                            <g:actionSubmit action="show" class="add" value="${g.message(code:'inventory.item.reorder.not.allowed')}" />
+                                        </span>
+                                        <span class="button">
+                                            <input type="button" class="search" value="Search"
+                                                        onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/search"' />
+                                        </span>
+                                    </g:form>
+                                </g:if>
+                                <g:else><!--Real order button.-->
+                                    <g:form controller="inventoryItemPurchaseDetailed">
+                                        <g:hiddenField name="inventoryItem.id" value="${inventoryItemInstance.id}" />
+                                        <span class="button">
+                                            <g:actionSubmit action="create" class="add" value="Order" />
+                                        </span>
+                                        <span class="button">
+                                            <g:actionSubmit action="search" class="search" value="Search" />
+                                        </span>
+                                    </g:form>
+                                </g:else>
+                            </div>
+
+                        </g:if>
+                        <g:else>
+
+                            <div class="list">
+                                <table>
+                                    <thead>
+                                        <tr>
+                                            <g:sortableColumn action="show" property="purchaseOrderNumber"
+                                                                                title="Order #" params="[paginate: 'purchases']"  />
+                                            <g:sortableColumn action="show"  property="date"
+                                                                                title="Date" params="[paginate: 'purchases']" />
+                                            <g:sortableColumn action="show"  property="costCode"
+                                                                                title="Cost Code" params="[paginate: 'purchases']" />
+                                            <g:sortableColumn action="show"  property="quantity"
+                                                                                title="Quantity" params="[paginate: 'purchases']" />
+                                            <g:sortableColumn action="show"  property="orderValueAmount"
+                                                                                title="Order \$" params="[paginate: 'purchases']" />
+                                            <g:sortableColumn action="show"  property="invoiceNumber"
+                                                                                title="Invoice Number" params="[paginate: 'purchases']" />
+                                            <g:sortableColumn action="show"  property="inventoryItemPurchaseType"
+                                                                                title="Type" params="[paginate: 'purchases']" />
+                                            <th>
+                                                <img  src="${resource(dir:'images/skin',file:'database_go_grey.png')}" alt="Show" title="Show" />
+                                            </th>
+                                            <th>
+                                                <img  src="${resource(dir:'images/skin',file:'basket_put_grey.png')}" alt="Receive" title="Receive" />
+                                            </th>
+                                            <th>
+                                                <img  src="${resource(dir:'images/skin',file:'tick_grey.png')}" alt="Approve" title="Approve Payment" />
+                                            </th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                        <g:each in="${inventoryItemPurchases}" status="i" var="purchase">
+                                            <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}"'>
+                                                    ${fieldValue(bean:purchase, field:'purchaseOrderNumber')}
+                                                </td>
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}"'>
+                                                    <g:formatDate date="${purchase.date}" format="EEE, dd-MMM-yyyy"/>
+                                                </td>
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}"'>
+                                                    ${fieldValue(bean:purchase, field:'costCode')}
+                                                </td>
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}"'>
+                                                    ${fieldValue(bean:purchase, field:'quantity')}
+                                                </td>
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}"'>
+                                                    ${fieldValue(bean:purchase, field:'orderValueAmount')}
+                                                    ${fieldValue(bean:purchase, field:'orderValueCurrency')}
+                                                </td>
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}"'>
+                                                    ${fieldValue(bean:purchase, field:'invoiceNumber')}
+                                                </td>
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}"'>
+                                                    ${fieldValue(bean:purchase, field:'inventoryItemPurchaseType')}
+                                                </td>
+                                                <td class="notClickable">
+                                                    <g:link controller="inventoryItemPurchaseDetailed" action="show" id="${purchase.id}">
+                                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" title="Show" />
+                                                    </g:link>
+                                                </td>
+
+                                                <g:if test="${purchase.inventoryItemPurchaseType.id == 1}">
+                                                    <g:if test="${!purchase.receivedComplete}">
+                                                        <td class="notClickable">
+                                                            <g:link controller="inventoryItemPurchaseDetailed" action="receive" params="[id: purchase.id, returnTo: 'inventoryItem']">
+                                                                <img  src="${resource(dir:'images/skin',file:'basket_put.png')}" alt="Receive" title="Receive" />
+                                                            </g:link>
+                                                        </td>
+                                                        <td class="notClickable">
+                                                        </td>
+                                                    </g:if>
+                                                    <g:else>
+                                                        <td class="notClickable">
+                                                        </td>
+                                                        <td class="notClickable">
+                                                        </td>
+                                                    </g:else>
+                                                </g:if>
+                                                <g:elseif test="${(purchase.inventoryItemPurchaseType.id == 2)||(purchase.inventoryItemPurchaseType.id == 3)}">
+                                                    <g:if test="${!purchase.invoicePaymentApproved}">
+                                                        <td class="notClickable">
+                                                        </td>
+                                                        <td class="notClickable">
+                                                            <g:link controller="inventoryItemPurchaseDetailed" action="approveInvoicePayment" params="[id: purchase.id, returnTo: 'inventoryItem']">
+                                                                <img  src="${resource(dir:'images/skin',file:'tick.png')}" alt="Approve" title="Approve Payment" />
+                                                            </g:link>
+                                                        </td>
+                                                    </g:if>
+                                                    <g:else>
+                                                        <td class="notClickable">
+                                                        </td>
+                                                        <td class="notClickable">
+                                                        </td>
+                                                    </g:else>
+                                                </g:elseif>
+                                                <g:else>
+                                                    <td class="notClickable">
+                                                    </td>
+                                                    <td class="notClickable">
+                                                    </td>
+                                                </g:else>
+
+                                            </tr>
+                                        </g:each>
+                                    </tbody>
+                                </table>
+                            </div>
+
+                            <div class="buttons">
+                                <!--Fake button to prevent ordering disabled inventory items-->
+                                <g:if test="${inventoryItemInstance.isObsolete || !inventoryItemInstance.isActive}" >
+                                    <g:form controller="inventoryItemDetailed">
+                                        <g:hiddenField name="id" value="${inventoryItemInstance.id}" />
+                                        Results: ${inventoryItemPurchases.size()} / ${inventoryItemPurchasesTotal}
+                                        <span class="button">
+                                            <g:actionSubmit action="show" class="add" value="${g.message(code:'inventory.item.reorder.not.allowed')}" />
+                                        </span>
+                                        <span class="button">
+                                            <input type="button" class="search" value="Search"
+                                                        onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/search"' />
+                                        </span>
+                                    </g:form>
+                                </g:if>
+                                <g:else><!--Real order button.-->
+                                    <g:form controller="inventoryItemPurchaseDetailed">
+                                        <g:hiddenField name="inventoryItem.id" value="${inventoryItemInstance.id}" />
+                                        Results: ${inventoryItemPurchases.size()} / ${inventoryItemPurchasesTotal}
+                                        <span class="button">
+                                            <g:actionSubmit action="create" class="add" value="Order" />
+                                        </span>
+                                        <span class="button">
+                                            <g:actionSubmit action="search" class="search" value="Search" />
+                                        </span>
+                                    </g:form>
+                                </g:else>
+                            </div>
+
+                            <div class="paginateButtons">
+                                <g:paginate action="show"
+                                                        id="${inventoryItemInstance?.id}"
+                                                        total="${inventoryItemPurchasesTotal}"
+                                                        params="[paginate: 'purchases']" />
+                            </div>
+
+                        </g:else>
+
+                    </richui:tabContent>
+<!-- End Movement tab -->
+
+                </richui:tabContents>
+            </richui:tabView>
+
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/approveInvoicePayment.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/approveInvoicePayment.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/approveInvoicePayment.gsp	(revision 753)
@@ -0,0 +1,122 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Approve Payment InventoryItemPurchase</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Approve Payment</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${inventoryItemPurchaseInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryItemPurchaseInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="approveInvoicePaymentSave" method="post" >
+                <g:hiddenField name="inventoryItem.id" value="${inventoryItemPurchaseInstance.inventoryItem?.id}" />
+                <g:hiddenField name="receivedId" value="${receivedId}" />
+                <g:hiddenField name="supplier.id" value="${inventoryItemPurchaseInstance.supplier?.id}" />
+                <g:hiddenField name="taskBudgetStatus.id" value="${inventoryItemPurchaseInstance.taskBudgetStatus?.id}" />
+                <g:hiddenField name="returnTo" value="${params.returnTo}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryItem">Inventory Item:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:link controller="inventoryItemDetailed"
+                                                    action="show"
+                                                    id="${inventoryItemPurchaseInstance.inventoryItem.id}">
+                                        ${inventoryItemPurchaseInstance.inventoryItem.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="purchaseOrderNumber">Purchase Order #:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    ${inventoryItemPurchaseInstance.purchaseOrderNumber.encodeAsHTML()}
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="costCode">Cost Code:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'costCode','errors')}">
+                                    ${inventoryItemPurchaseInstance.costCode.encodeAsHTML()}
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskBudgetStatus">Budget Status:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'taskBudgetStatus','errors')}">
+                                    ${inventoryItemPurchaseInstance.taskBudgetStatus.encodeAsHTML()}
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="quantity">Invoice #:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'invoiceNumber','errors')}">
+                                    <input type="text" id="invoiceNumber" name="invoiceNumber" value="${fieldValue(bean:inventoryItemPurchaseInstance,field:'invoiceNumber')}" />
+                                    <g:helpBalloon code="inventoryItemPurchase.invoice.number" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="quantity">Quantity:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'quantity','errors')}">
+                                    <input type="text" id="quantity" name="quantity" value="${fieldValue(bean:inventoryItemPurchaseInstance,field:'quantity')}" />
+                                    ${inventoryItemPurchaseInstance.inventoryItem.unitOfMeasure.encodeAsHTML()}
+                                    <g:helpBalloon code="inventoryItemPurchase.approve.quantity" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="orderValue">Approve Value:</label>
+                                </td>
+                                <td valign="top">
+                                    <input  class="medium ${hasErrors(bean:inventoryItemPurchaseInstance,field:'orderValueAmount','errors')}"
+                                                    type="text" id="orderValueAmount" name="orderValueAmount"
+                                                    value="${fieldValue(bean:inventoryItemPurchaseInstance,field:'orderValueAmount')}" />
+                                    ${inventoryItemPurchaseInstance.orderValueCurrency?.encodeAsHTML()}
+                                    <g:helpBalloon code="inventoryItemPurchase.approve.value" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:inventoryItemPurchaseInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/create.gsp	(revision 753)
@@ -0,0 +1,159 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create InventoryItemPurchase</title>
+        <nav:resources override="true"/>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Order Inventory</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:if test="${!costCodes}" >
+                <div class="errors">
+                    <ul>
+                        <li><g:message code="inventoryItemPurchase.costCodes.not.found" /><li>
+                </div>
+            </g:if>
+            <g:hasErrors bean="${inventoryItemPurchaseInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryItemPurchaseInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <g:hiddenField name="inventoryItem.id" value="${inventoryItemPurchaseInstance?.inventoryItem?.id}" />
+                <g:hiddenField name="returnTo" value="${params.returnTo}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryItem">Inventory Item:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:link controller="inventoryItemDetailed"
+                                                    action="show"
+                                                    id="${inventoryItemPurchaseInstance.inventoryItem.id}">
+                                        ${inventoryItemPurchaseInstance.inventoryItem.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="purchaseOrderNumber">Purchase Order #:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'purchaseOrderNumber','errors')}">
+                                    <input type="text" maxlength="50" id="purchaseOrderNumber" name="purchaseOrderNumber" value="${fieldValue(bean:inventoryItemPurchaseInstance,field:'purchaseOrderNumber')}"/>
+                                    <g:helpBalloon code="inventoryItemPurchase.purchaseOrderNumber" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="date">Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'date','errors')}">
+                                    <richui:dateChooser name="date" format="dd-MM-yyyy" value="${inventoryItemPurchaseInstance.date}" />
+                                    <g:helpBalloon code="inventoryItemPurchase.order.placed.date" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="costCode">Cost Code:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'costCode','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${ costCodes }"
+                                                        name="costCode.id"
+                                                        value="${inventoryItemPurchaseInstance?.costCode?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.please.select.text')}/]">
+                                    </g:select>
+                                    <g:helpBalloon code="inventoryItemPurchase.cost.code" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskBudgetStatus">Budget Status:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'taskBudgetStatus','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${ TaskBudgetStatus.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }"
+                                                        name="taskBudgetStatus.id"
+                                                        value="${inventoryItemPurchaseInstance?.taskBudgetStatus?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.please.select.text')}/]">
+                                    </g:select>
+                                    <g:helpBalloon code="inventoryItemPurchase.task.budget.status" />
+                                </td>
+                            </tr>
+                        
+                             <tr class="prop">
+                                 <td valign="top" class="name">
+                                    <label for="supplier">Supplier:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'supplier','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${ Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }"
+                                                        name="supplier.id"
+                                                        value="${inventoryItemPurchaseInstance?.supplier?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.please.select.text')}/]">
+                                    </g:select>
+                                    <g:helpBalloon code="inventoryItemPurchase.supplier" />
+                                    <p><g:link controller="supplierDetailed" action="create">+Add Supplier</g:link></p>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="quantity">Quantity:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'quantity','errors')}">
+                                    <input type="text" id="quantity" name="quantity" value="${fieldValue(bean:inventoryItemPurchaseInstance,field:'quantity')}" />
+                                    ${inventoryItemPurchaseInstance.inventoryItem.unitOfMeasure.encodeAsHTML()}
+                                    <g:helpBalloon code="inventoryItemPurchase.quantity" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="orderValue">Order Value:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <input  class="medium ${hasErrors(bean:inventoryItemPurchaseInstance,field:'orderValueAmount','errors')}"
+                                                    type="text" id="orderValueAmount" name="orderValueAmount"
+                                                    value="${inventoryItemPurchaseInstance.orderValueAmount}" />
+                                    <g:currencySelect name="orderValueCurrency"
+                                                                        value="${inventoryItemPurchaseInstance?.orderValueCurrency}"
+                                                                        from="${grailsApplication.config.currencyList}">
+                                    </g:currencySelect>
+                                    <g:helpBalloon code="inventoryItemPurchase.order.value" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:inventoryItemPurchaseInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,229 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit InventoryItemPurchase</title>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit InventoryItemPurchase</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${inventoryItemPurchaseInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryItemPurchaseInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${inventoryItemPurchaseInstance?.id}" />
+                <input type="hidden" name="version" value="${inventoryItemPurchaseInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                    
+                            <tr class="prop">
+                                <td valign="top" class="name">Inventory Item:</td>
+                                
+                                <td valign="top" class="value"><g:link controller="inventoryItemDetailed" action="show" id="${inventoryItemPurchaseInstance?.inventoryItem?.id}">${inventoryItemPurchaseInstance?.inventoryItem?.encodeAsHTML()}</g:link></td>
+                                
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">Purchase Type:</td>
+                                
+                                <td valign="top" class="value">${inventoryItemPurchaseInstance?.inventoryItemPurchaseType?.encodeAsHTML()}</td>
+                                
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="invoiceNumber">Purchase Order #:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'purchaseOrderNumber','errors')}">
+                                    <input type="text" maxlength="50" id="purchaseOrderNumber" name="purchaseOrderNumber" value="${fieldValue(bean:inventoryItemPurchaseInstance,field:'purchaseOrderNumber')}"/>
+                                    <g:helpBalloon code="inventoryItemPurchase.purchaseOrderNumber" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="date">Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'date','errors')}">
+                                    <richui:dateChooser name="date" format="dd-MM-yyyy" value="${inventoryItemPurchaseInstance.date}" />
+                                    <g:helpBalloon code="inventoryItemPurchase.order.placed.date" />
+                                </td>
+                            </tr> 
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="costCode">Cost Code:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'costCode','errors')}">
+                                    <g:if test="${costCodes}">
+                                        <g:select optionKey="id"
+                                                            from="${ costCodes }"
+                                                            name="costCode.id"
+                                                            value="${inventoryItemPurchaseInstance.costCode?.id}" >
+                                        </g:select>
+                                    </g:if>
+                                    <g:else>
+                                        <g:link controller="costCodeDetailed" action="show" id="${inventoryItemPurchaseInstance?.costCode?.id}">
+                                            ${inventoryItemPurchaseInstance?.costCode?.encodeAsHTML()}
+                                        </g:link>
+                                    </g:else>
+                                    <g:helpBalloon code="inventoryItemPurchase.cost.code" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskBudgetStatus">Budget Status:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'taskBudgetStatus','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${ TaskBudgetStatus.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }"
+                                                        name="taskBudgetStatus.id"
+                                                        value="${inventoryItemPurchaseInstance?.taskBudgetStatus?.id}" >
+                                    </g:select>
+                                    <g:helpBalloon code="inventoryItemPurchase.task.budget.status" />
+                                </td>
+                            </tr>
+                        
+                             <tr class="prop">
+                                 <td valign="top" class="name">
+                                    <label for="supplier">Supplier:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'supplier','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${ Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }"
+                                                        name="supplier.id"
+                                                        value="${inventoryItemPurchaseInstance?.supplier?.id}">
+                                    </g:select>
+                                    <g:helpBalloon code="inventoryItemPurchase.supplier" />
+                                    <p><g:link controller="supplierDetailed" action="create">+Add Supplier</g:link></p>
+                                </td>
+                            </tr>
+                    
+                            <tr class="prop">
+                                <td valign="top" class="name">Quantity:</td>
+                                
+                                <td valign="top" class="value">
+                                    ${fieldValue(bean:inventoryItemPurchaseInstance, field:'quantity')}
+                                    <g:helpBalloon code="inventoryItemPurchase.quantity" />
+                                </td>
+                                
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="orderValueAmount">Order Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'orderValueAmount','errors')}">
+                                    <input type="text" id="orderValueAmount" name="orderValueAmount" value="${fieldValue(bean:inventoryItemPurchaseInstance,field:'orderValueAmount')}" />
+                                    <g:currencySelect name="orderValueCurrency"
+                                                                        value="${inventoryItemPurchaseInstance?.orderValueCurrency}"
+                                                                        from="${grailsApplication.config.currencyList}">
+                                    </g:currencySelect>
+                                    <g:helpBalloon code="inventoryItemPurchase.order.value" />
+                                </td>
+                            </tr>
+
+                            <g:if test="${inventoryItemPurchaseInstance.inventoryItemPurchaseType?.id == 4}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="invoiceNumber">Invoice Number:</label>
+                                    </td>
+                                    <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'invoiceNumber','errors')}">
+                                        <input type="text" maxlength="50" id="invoiceNumber" name="invoiceNumber" value="${fieldValue(bean:inventoryItemPurchaseInstance,field:'invoiceNumber')}"/>
+                                    <g:helpBalloon code="inventoryItemPurchase.invoice.number" />
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                            <g:if test="${inventoryItemPurchaseInstance?.inventoryItemPurchaseType?.id > 0}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="receivedComplete">Received Complete:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:checkBox name="receivedComplete" value="${inventoryItemPurchaseInstance?.receivedComplete}" ></g:checkBox>
+                                    </td>
+                                </tr>
+                                
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="invoicePaymentApproved">Invoice Payment Approved:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:checkBox name="invoicePaymentApproved" value="${inventoryItemPurchaseInstance?.invoicePaymentApproved}" ></g:checkBox>
+                                    </td>
+                                </tr>
+                            </g:if>
+                            <g:else>
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="receivedComplete">Received Complete:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        ${fieldValue(bean:inventoryItemPurchaseInstance, field:'receivedComplete')}
+                                    </td>
+                                </tr>
+
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="invoicePaymentApproved">Invoice Payment Approved:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        ${fieldValue(bean:inventoryItemPurchaseInstance, field:'invoicePaymentApproved')}
+                                    </td>
+                                </tr>
+                            </g:else>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:inventoryItemPurchaseInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr>
+                        
+                        <tr class="prop">
+                            <td valign="top" class="name">Entered By:</td>
+                            <td valign="top" class="value">
+                                <g:link controller="person" action="show" id="${inventoryItemPurchaseInstance?.enteredBy?.id}">
+                                    ${inventoryItemPurchaseInstance?.enteredBy?.encodeAsHTML()}
+                                </g:link>
+                                    on <g:formatDate date="${inventoryItemPurchaseInstance?.dateCreated}" format="EEE, dd-MMM-yyyy @ HH:mm"/>
+                            </td>
+                        </tr>
+
+                        <g:if test="${inventoryItemPurchaseInstance.lastUpdatedBy}">
+                            <tr class="prop">
+                                <td valign="top" class="name">Last Updated By:</td>
+                                <td valign="top" class="value">
+                                    <g:link controller="person" action="show" id="${inventoryItemPurchaseInstance?.lastUpdatedBy?.id}">
+                                        ${inventoryItemPurchaseInstance?.lastUpdatedBy.encodeAsHTML()}
+                                    </g:link>
+                                    on <g:formatDate date="${inventoryItemPurchaseInstance?.lastUpdated}" format="EEE, dd-MMM-yyyy @ HH:mm"/>
+                                </td>
+                            </tr>
+                        </g:if >
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/receive.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/receive.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/receive.gsp	(revision 753)
@@ -0,0 +1,119 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Receive InventoryItemPurchase</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Receive Inventory</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${inventoryItemPurchaseInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryItemPurchaseInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="receiveSave" method="post" >
+                <g:hiddenField name="inventoryItem.id" value="${inventoryItemPurchaseInstance.inventoryItem?.id}" />
+                <g:hiddenField name="orderId" value="${orderId}" />
+                <g:hiddenField name="supplier.id" value="${inventoryItemPurchaseInstance.supplier?.id}" />
+                <g:hiddenField name="taskBudgetStatus.id" value="${inventoryItemPurchaseInstance.taskBudgetStatus?.id}" />
+                <g:hiddenField name="returnTo" value="${params.returnTo}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryItem">Inventory Item:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:link controller="inventoryItemDetailed"
+                                                    action="show"
+                                                    id="${inventoryItemPurchaseInstance.inventoryItem.id}">
+                                        ${inventoryItemPurchaseInstance.inventoryItem.encodeAsHTML()}
+                                    </g:link>
+                                    <br />
+                                    Description: ${inventoryItemPurchaseInstance.inventoryItem.description.encodeAsHTML()}
+                                    <br />
+                                    Location: ${inventoryItemPurchaseInstance.inventoryItem.inventoryLocation.encodeAsHTML()}
+                                    <br />
+                                    Suppliers Part Number: ${inventoryItemPurchaseInstance.inventoryItem.suppliersPartNumber.encodeAsHTML()}
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="purchaseOrderNumber">Purchase Order #:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    ${inventoryItemPurchaseInstance.purchaseOrderNumber.encodeAsHTML()}
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="costCode">Cost Code:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'costCode','errors')}">
+                                    ${inventoryItemPurchaseInstance.costCode.encodeAsHTML()}
+                                </td>
+                            </tr> 
+                        
+                             <tr class="prop">
+                                 <td valign="top" class="name">
+                                    <label for="supplier">Supplier:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'supplier','errors')}">
+                                    ${inventoryItemPurchaseInstance.supplier}
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="quantity">Quantity:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'quantity','errors')}">
+                                    <input type="text" id="quantity" name="quantity" value="${fieldValue(bean:inventoryItemPurchaseInstance,field:'quantity')}" />
+                                    ${inventoryItemPurchaseInstance.inventoryItem.unitOfMeasure.encodeAsHTML()}
+                                    <g:helpBalloon code="inventoryItemPurchase.receive.quantity" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="orderValueAmount">Receive Value:</label>
+                                </td>
+                                <td valign="top">
+                                    <input  class="medium ${hasErrors(bean:inventoryItemPurchaseInstance,field:'orderValueAmount','errors')}"
+                                                    type="text" id="orderValueAmount" name="orderValueAmount"
+                                                    value="${fieldValue(bean:inventoryItemPurchaseInstance,field:'orderValueAmount')}" />
+                                    ${inventoryItemPurchaseInstance.orderValueCurrency?.encodeAsHTML()}
+                                    <g:helpBalloon code="inventoryItemPurchase.receive.value" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryItemPurchaseInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:inventoryItemPurchaseInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/search.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/search.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/search.gsp	(revision 753)
@@ -0,0 +1,252 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Inventory Item Purchase Search</title>
+        <filterpane:includes />
+        <nav:resources override="true"/>
+        <export:resource />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <filterpane:currentCriteria domainBean="InventoryItemPurchase"
+                                    action="search"
+                                    dateFormat="EEE, dd-MMM-yyyy"
+                                    removeImgDir="images"
+                                    removeImgFile="bullet_delete.png"
+                                    title="Advanced Search"/>
+
+            <div class="paginateButtons">
+                <span class="searchButtons">
+                    <a href='' onclick="showElement('searchPane'); return false;">Quick</a>
+                </span>
+                Results: ${inventoryItemPurchaseList.size()} / ${inventoryItemPurchaseTotal}
+                <span class="searchButtons">
+                    <filterpane:filterButton text="Advanced" appliedText="Advanced" />
+                </span>
+            </div>
+
+            <jsUtil:toggleControl toggleId="options"
+                                                    imageId="optionsImg"
+                                                    closedImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_right.png')}"
+                                                    openImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_down.png')}"
+                                                    text="${g.message(code: 'default.options.text')}"
+                                                    />
+
+            <div id="options" style="display:none;">
+                <g:form method="post" action="setSearchParamsMax" >
+                    <g:hiddenField name="params" value="${filterParams}" />
+                    <div class="dialog">
+                        <table>
+                            <tbody>
+
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="max">Results per page:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <input type="text" maxlength="4" id="description" name="newMax" value="${params.max}"/>
+
+                                        <span class="buttons">
+                                            <g:actionSubmit action="setSearchParamsMax" class="go" value="Update" />
+                                        </span>
+                                    </td>
+                                </tr>
+
+                            </tbody>
+                        </table>
+                    </div>
+                <export:formats  params="${filterParams}" formats="['csv', 'excel', 'pdf', 'rtf']"/>
+                </g:form>
+            </div>
+
+            <br />
+
+            <g:if test="${inventoryItemPurchaseList.size() > 10}">
+                <g:if test="${inventoryItemPurchaseTotal > inventoryItemPurchaseList.size()}">
+                    <div class="paginateButtons">
+                        <g:paginate action="search" total="${inventoryItemPurchaseTotal}" params="${filterParams}" />
+                    </div>
+                </g:if>
+            </g:if>
+
+            <g:if test="${inventoryItemPurchaseList.size() > 0}">
+                <div class="list">
+                    <table>
+                        <thead>
+                            <tr>
+                                <g:sortableColumn property="purchaseOrderNumber"
+                                                                    title="Order #"
+                                                                    params="${filterParams}"  />
+                                <g:sortableColumn property="date"
+                                                                    title="Date"
+                                                                    params="${filterParams}" />
+                                <g:sortableColumn property="inventoryItem"
+                                                                    title="Inventory Item"
+                                                                    params="${filterParams}" />
+                                <g:sortableColumn property="costCode"
+                                                                    title="Cost Code"
+                                                                    params="${filterParams}" />
+                                <g:sortableColumn property="quantity"
+                                                                    title="Quantity"
+                                                                    params="${filterParams}" />
+                                <g:sortableColumn property="orderValueAmount"
+                                                                    title="Order \$"
+                                                                    params="${filterParams}" />
+                                <g:sortableColumn property="inventoryItemPurchaseType"
+                                                                    title="Type"
+                                                                    params="${filterParams}" />
+                                <th>
+                                    <img  src="${resource(dir:'images/skin',file:'database_go_grey.png')}" alt="Show" title="Show" />
+                                </th>
+                                <th>
+                                    <img  src="${resource(dir:'images/skin',file:'basket_put_grey.png')}" alt="Receive" title="Receive" />
+                                </th>
+                                <th>
+                                    <img  src="${resource(dir:'images/skin',file:'tick_grey.png')}" alt="Approve" title="Approve Payment" />
+                                </th>
+                            </tr>
+                        </thead>
+                        <tbody>
+                            <g:each in="${inventoryItemPurchaseList}" status="i" var="purchase">
+                                <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                    <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}?returnTo=search"'>
+                                        ${fieldValue(bean:purchase, field:'purchaseOrderNumber')}
+                                    </td>
+                                    <td style="width:75px;" onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}?returnTo=search"'>
+                                        <g:formatDate date="${purchase.date}" format="EEE, dd-MMM-yyyy"/>
+                                    </td>
+                                    <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}?returnTo=search"'>
+                                        <b>${fieldValue(bean:purchase, field:'inventoryItem')}</b><br/>
+                                        ${purchase.inventoryItem.description?.encodeAsHTML()}
+                                    </td>
+                                    <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}?returnTo=search"'>
+                                        <b>${fieldValue(bean:purchase, field:'costCode')}</b><br/>
+                                        <g:if test="${purchase.invoiceNumber}">
+                                            Invoice # ${fieldValue(bean:purchase, field:'invoiceNumber')}<br/>
+                                        </g:if>
+                                        ${fieldValue(bean:purchase, field:'comment')}
+                                    </td>
+                                    <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}?returnTo=search"'>
+                                        ${fieldValue(bean:purchase, field:'quantity')}
+                                    </td>
+                                    <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}?returnTo=search"'>
+                                        ${fieldValue(bean:purchase, field:'orderValueAmount')}
+                                        ${fieldValue(bean:purchase, field:'orderValueCurrency')}
+                                    </td>
+                                    <td onclick='window.location = "${request.getContextPath()}/inventoryItemPurchaseDetailed/show/${purchase.id}?returnTo=search"'>
+                                        ${fieldValue(bean:purchase, field:'inventoryItemPurchaseType')}
+                                    </td>
+                                    <td class="notClickable">
+                                        <g:link controller="inventoryItemPurchaseDetailed" action="show" params="[id: purchase.id, returnTo: 'search']">
+                                            <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" title="Show" />
+                                        </g:link>
+                                    </td>
+
+                                    <g:if test="${purchase.inventoryItemPurchaseType.id == 1}">
+                                        <g:if test="${!purchase.receivedComplete}">
+                                            <td class="notClickable">
+                                                <g:link controller="inventoryItemPurchaseDetailed" action="receive" params="[id: purchase.id, returnTo: 'search']">
+                                                    <img  src="${resource(dir:'images/skin',file:'basket_put.png')}" alt="Receive" title="Receive" />
+                                                </g:link>
+                                            </td>
+                                            <td class="notClickable">
+                                            </td>
+                                        </g:if>
+                                        <g:else>
+                                            <td class="notClickable">
+                                            </td>
+                                            <td class="notClickable">
+                                            </td>
+                                        </g:else>
+                                    </g:if>
+                                    <g:elseif test="${(purchase.inventoryItemPurchaseType.id == 2)||(purchase.inventoryItemPurchaseType.id == 3)}">
+                                        <g:if test="${!purchase.invoicePaymentApproved}">
+                                            <td class="notClickable">
+                                            </td>
+                                            <td class="notClickable">
+                                                <g:link controller="inventoryItemPurchaseDetailed" action="approveInvoicePayment" params="[id: purchase.id, returnTo: 'search']">
+                                                    <img  src="${resource(dir:'images/skin',file:'tick.png')}" alt="Approve" title="Approve Payment" />
+                                                </g:link>
+                                            </td>
+                                        </g:if>
+                                        <g:else>
+                                            <td class="notClickable">
+                                            </td>
+                                            <td class="notClickable">
+                                            </td>
+                                        </g:else>
+                                    </g:elseif>
+                                    <g:else>
+                                        <td class="notClickable">
+                                        </td>
+                                        <td class="notClickable">
+                                        </td>
+                                    </g:else>
+
+                                </tr>
+                            </g:each>
+                        </tbody>
+                    </table>
+                </div>
+            </g:if>
+            <div class="paginateButtons">
+                <g:paginate action="search" total="${inventoryItemPurchaseTotal}" params="${filterParams}" />
+            </div>
+
+            <filterpane:filterPane domainBean="InventoryItemPurchase"
+                                    title="Advanced Search"
+                                    action="search"
+                                    class="overlayPane"
+                                    excludeProperties="orderValueCurrency, dateCreated"
+                                    associatedProperties="inventoryItemPurchaseType.name, supplier.name"
+                                    filterPropertyValues="${['inventoryItemPurchaseType.name':[values:InventoryItemPurchaseType.findAllByIsActive(true)],
+                                                                                'supplier.name':[values:Supplier.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }],
+                                                                                date:[years: associatedPropertyValues.yearRange,precision:'day']
+                                                                                ]}"/>
+        </div> <!-- end body  -->
+
+        <!-- Start Search Pane -->
+        <div class="overlayPane" id="searchPane" style="display:none;">
+            <h2>Quick Search</h2>
+            <g:form method="post" id="searchForm" name="searchForm" >
+                <table>
+                    <tbody>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label>Type:</label>
+                            </td>
+                            <td valign="top" class="value">
+                                <g:link controller="inventoryItemPurchaseDetailed"
+                                                action="search"
+                                                params="[quickSearch: 'searchAllOrders']">
+                                                All Orders
+                                </g:link>
+                                <br />
+                                <g:link controller="inventoryItemPurchaseDetailed" 
+                                                action="search"
+                                                params="[quickSearch: 'searchAllReceived']">
+                                                All Received
+                                </g:link>
+                            </td>
+                        </tr>
+
+                    </tbody>
+                </table>
+                <div class="buttons">
+                    <span class="button">
+                        <input type="button" value="${g.message(code:'fp.tag.filterPane.button.cancel.text', default:'Cancel')}" onclick="return hideElement('searchPane');" />
+                    </span>
+                </div>
+            </g:form>
+        </div> <!-- end search pane -->
+
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryItemPurchaseDetailed/show.gsp	(revision 753)
@@ -0,0 +1,151 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show InventoryItemPurchase</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Inventory Item:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="inventoryItemDetailed" action="show" id="${inventoryItemPurchaseInstance?.inventoryItem?.id}">${inventoryItemPurchaseInstance?.inventoryItem?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Purchase Type:</td>
+                            
+                            <td valign="top" class="value">${inventoryItemPurchaseInstance?.inventoryItemPurchaseType?.encodeAsHTML()}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Purchase Order #:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryItemPurchaseInstance, field:'purchaseOrderNumber')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Date:</td>
+                            <td valign="top" class="value">
+                                <g:formatDate date="${inventoryItemPurchaseInstance?.date}" format="EEE, dd-MMM-yyyy"/>
+                            </td>
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Cost Code:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="costCodeDetailed" action="show" id="${inventoryItemPurchaseInstance?.costCode?.id}">${inventoryItemPurchaseInstance?.costCode?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Budget Status:</td>
+                            
+                            <td valign="top" class="value">${inventoryItemPurchaseInstance?.taskBudgetStatus?.encodeAsHTML()}</td>
+                            
+                        </tr>
+                        
+                         <tr class="prop">
+                            <td valign="top" class="name">Supplier:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="supplierDetailed" action="show" id="${inventoryItemPurchaseInstance?.supplier?.id}">${inventoryItemPurchaseInstance?.supplier?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Quantity:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryItemPurchaseInstance, field:'quantity')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Order Value:</td>
+                            
+                            <td valign="top" class="value">
+                                ${fieldValue(bean:inventoryItemPurchaseInstance, field:'orderValueAmount')}
+                                ${inventoryItemPurchaseInstance.orderValueCurrency?.encodeAsHTML()}
+                            </td>
+                            
+                        </tr>
+
+                        <g:if test="${inventoryItemPurchaseInstance.inventoryItemPurchaseType?.id == 4}">
+                            <tr class="prop">
+                                <td valign="top" class="name">Invoice Number:</td>
+                                <td valign="top" class="value">${fieldValue(bean:inventoryItemPurchaseInstance, field:'invoiceNumber')}</td>
+                            </tr>
+                        </g:if>
+                        
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label for="receivedComplete">Received Complete:</label>
+                            </td>
+                            <td valign="top" class="value">
+                                ${inventoryItemPurchaseInstance?.receivedComplete}
+                            </td>
+                        </tr>
+                        
+                        <tr class="prop">
+                            <td valign="top" class="name">
+                                <label for="invoicePaymentApproved">Invoice Payment Approved:</label>
+                            </td>
+                            <td valign="top" class="value">
+                                ${inventoryItemPurchaseInstance?.invoicePaymentApproved}
+                            </td>
+                        </tr>
+                        
+                        <tr class="prop">
+                            <td valign="top" class="name">Comment:</td>
+                            <td valign="top" class="value">${fieldValue(bean:inventoryItemPurchaseInstance, field:'comment')}</td>
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Entered By:</td>
+                            <td valign="top" class="value">
+                                <g:link controller="person" action="show" id="${inventoryItemPurchaseInstance?.enteredBy?.id}">
+                                    ${inventoryItemPurchaseInstance?.enteredBy?.encodeAsHTML()}
+                                </g:link>
+                                    on <g:formatDate date="${inventoryItemPurchaseInstance?.dateCreated}" format="EEE, dd-MMM-yyyy @ HH:mm"/>
+                            </td>
+                        </tr>
+
+                        <g:if test="${inventoryItemPurchaseInstance.lastUpdatedBy}">
+                            <tr class="prop">
+                                <td valign="top" class="name">Last Updated By:</td>
+                                <td valign="top" class="value">
+                                    <g:link controller="person" action="show" id="${inventoryItemPurchaseInstance?.lastUpdatedBy?.id}">
+                                        ${inventoryItemPurchaseInstance?.lastUpdatedBy.encodeAsHTML()}
+                                    </g:link>
+                                    on <g:formatDate date="${inventoryItemPurchaseInstance?.lastUpdated}" format="EEE, dd-MMM-yyyy @ HH:mm"/>
+                                </td>
+                            </tr>
+                        </g:if >
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <g:hiddenField name="id" value="${inventoryItemPurchaseInstance?.id}" />
+                    <g:hiddenField name="returnTo" value="${params.returnTo}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create InventoryLocation</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryLocationInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryLocationInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryLocationInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:inventoryLocationInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryStore">Inventory Store:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryLocationInstance,field:'inventoryStore','errors')}">
+                                    <g:select optionKey="id" from="${InventoryStore.list()}" name="inventoryStore.id" value="${inventoryLocationInstance?.inventoryStore?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryLocationInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryLocationInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit InventoryLocation</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryLocationInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryLocationInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${inventoryLocationInstance?.id}" />
+                <input type="hidden" name="version" value="${inventoryLocationInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryLocationInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:inventoryLocationInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryStore">Inventory Store:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryLocationInstance,field:'inventoryStore','errors')}">
+                                    <g:select optionKey="id" from="${InventoryStore.list()}" name="inventoryStore.id" value="${inventoryLocationInstance?.inventoryStore?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryLocationInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryLocationInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryItems">Inventory Items:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryLocationInstance,field:'inventoryItems','errors')}">
+                                    
+<ul>
+<g:each var="i" in="${inventoryLocationInstance?.inventoryItems?}">
+    <li><g:link controller="inventoryItemDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="inventoryItemDetailed" params="['inventoryLocation.id':inventoryLocationInstance?.id]" action="create">+Add Inventory Item</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/list.gsp	(revision 753)
@@ -0,0 +1,72 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>InventoryLocation List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                            <g:sortableColumn property="id" title="Id" />
+
+                            <g:sortableColumn property="name" title="Name" />
+
+                            <th>Inventory Store</th>
+
+                            <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${inventoryLocationInstanceList}" status="i" var="inventoryLocationInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryLocationDetailed/show/${inventoryLocationInstance.id}"'>
+                                ${fieldValue(bean:inventoryLocationInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryLocationDetailed/show/${inventoryLocationInstance.id}"'>
+                                ${fieldValue(bean:inventoryLocationInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryLocationDetailed/show/${inventoryLocationInstance.id}"'>
+                                ${fieldValue(bean:inventoryLocationInstance, field:'inventoryStore')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryLocationDetailed/show/${inventoryLocationInstance.id}"'>
+                                ${fieldValue(bean:inventoryLocationInstance, field:'isActive')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${inventoryLocationInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${inventoryLocationInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryLocationDetailed/show.gsp	(revision 753)
@@ -0,0 +1,76 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show InventoryLocation</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryLocationInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryLocationInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Inventory Store:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="inventoryStoreDetailed" action="show" id="${inventoryLocationInstance?.inventoryStore?.id}">${inventoryLocationInstance?.inventoryStore?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryLocationInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Inventory Items:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="i" in="${inventoryLocationInstance.inventoryItems}">
+                                    <li><g:link controller="inventoryItemDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${inventoryLocationInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryMovementDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryMovementDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryMovementDetailed/create.gsp	(revision 753)
@@ -0,0 +1,86 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create InventoryMovement</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Inventory Movement</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryMovementInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryMovementInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+
+            <g:form action="save" method="post" >
+                <g:hiddenField name="inventoryItem.id" value="${inventoryMovementInstance?.inventoryItem?.id}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryItem">Inventory Item:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementInstance,field:'inventoryItem','errors')}">
+                                    <g:link controller="inventoryItemDetailed" action="show" id="${inventoryMovementInstance?.inventoryItem?.id}" >
+                                        <g:fieldValue bean="${inventoryMovementInstance}" field="inventoryItem" />
+                                    </g:link>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="quantity">Quantity:</label>
+                                </td>
+                                <td valign="top">
+                                    <input class="medium ${hasErrors(bean:inventoryMovementInstance,field:'quantity','errors')}"
+                                                type="text" id="quantity" name="quantity"
+                                                value="${fieldValue(bean:inventoryMovementInstance,field:'quantity')}"/>
+                                                ${inventoryMovementInstance?.inventoryItem?.unitOfMeasure.encodeAsHTML()}
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryMovementType">Movement Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementInstance,field:'inventoryMovementType','errors')}">
+                                    <g:select optionKey="id" from="${inventoryMovementTypeList}" name="inventoryMovementType.id" value="${inventoryMovementInstance?.inventoryMovementType?.id}" ></g:select>
+                                </td>
+                            </tr>
+
+                            <g:if test="${inventoryMovementInstance?.task}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="taskInstance">Linking with task:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <g:hiddenField name="task.id" value="${inventoryMovementInstance.task.id}" />
+                                        <g:link controller="taskDetailed" action="show" id="${inventoryMovementInstance.task.id}" >
+                                            ${inventoryMovementInstance.task.encodeAsHTML()}
+                                        </g:link>
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                        </tbody>
+                    </table>
+                </div>
+
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryMovementDetailed/listInventoryMovements.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryMovementDetailed/listInventoryMovements.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryMovementDetailed/listInventoryMovements.gsp	(revision 753)
@@ -0,0 +1,76 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Inventory Movement List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>List Inventory Movements</h1>
+        </div>
+        <div class="body">
+             <g:link controller="inventoryItemDetailed" action="show" id="${inventoryItemInstance.id}">
+                <h1>Inventory Item: ${inventoryItemInstance.name.encodeAsHTML()}.</h1>
+            </g:link>
+            <g:if test="${flash.message}">
+                <div class="message">${flash.message}</div>
+            </g:if>
+
+            <div class="paginateButtons">
+                Results:${inventoryMovementListTotal}
+            </div>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn action="listInventoryMovements" property="quantity" title="Quantity" params="[id: inventoryItemInstance.id]"/>
+                        
+                   	        <g:sortableColumn action="listInventoryMovements"  property="inventoryMovementType" title="Movement Type" params="[id: inventoryItemInstance.id]" />
+                        
+                            <g:sortableColumn action="listInventoryMovements"  property="date" title="Date" params="[id: inventoryItemInstance.id]" />
+                        
+                   	        <g:sortableColumn action="listInventoryMovements"  property="person" title="Person" params="[id: inventoryItemInstance.id]" />
+
+                            <th></th>
+                   	    
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${inventoryMovementList}" status="i" var="inventoryMovementInstance">
+                    <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${inventoryMovementInstance.id}"'>
+                                ${fieldValue(bean:inventoryMovementInstance, field:'quantity')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${inventoryMovementInstance.id}"'>
+                                ${fieldValue(bean:inventoryMovementInstance, field:'inventoryMovementType')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${inventoryMovementInstance.id}"'>
+                                <g:formatDate date="${inventoryMovementInstance.date}" format="EEE, dd-MMM-yyyy"/>
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${inventoryMovementInstance.id}"'>
+                                ${fieldValue(bean:inventoryMovementInstance, field:'person')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${inventoryMovementInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate action="listInventoryMovements" id="${inventoryItemInstance.id}" total="${inventoryMovementListTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryMovementDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryMovementDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryMovementDetailed/show.gsp	(revision 753)
@@ -0,0 +1,92 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show InventoryMovement</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Inventory Movement</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryMovementInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryMovementInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryMovementInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Inventory Item:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="inventoryItemDetailed" action="show" id="${inventoryMovementInstance?.inventoryItem?.id}">${inventoryMovementInstance?.inventoryItem?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Quantity:</td>
+                            
+                            <td valign="top" class="value">
+                                ${fieldValue(bean:inventoryMovementInstance, field:'quantity')}
+                                ${inventoryMovementInstance.inventoryItem.unitOfMeasure.encodeAsHTML()}
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Movement Type:</td>
+                            
+                            <td valign="top" class="value">${inventoryMovementInstance?.inventoryMovementType?.encodeAsHTML()}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Task:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="taskDetailed" action="show" id="${inventoryMovementInstance?.task?.id}">${inventoryMovementInstance?.task?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Date:</td>
+                            
+                            <td valign="top" class="value">
+                                <g:formatDate date="${inventoryMovementInstance?.date}" format="EEE, dd-MMM-yyyy @ HH:mm"/>
+                            </td>
+                            
+                        </tr>
+
+                         <tr class="prop">
+                            <td valign="top" class="name">Person:</td>
+
+                            <td valign="top" class="value">${inventoryMovementInstance?.person?.encodeAsHTML()}</td>
+
+                        </tr>
+
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${inventoryMovementInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/create.gsp	(revision 753)
@@ -0,0 +1,73 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create InventoryMovementType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">InventoryMovementType List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create InventoryMovementType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryMovementTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryMovementTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementTypeInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:inventoryMovementTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="incrementsInventory">Increments Inventory:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementTypeInstance,field:'incrementsInventory','errors')}">
+                                    <g:checkBox name="incrementsInventory" value="${inventoryMovementTypeInstance?.incrementsInventory}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryMovementTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementTypeInstance,field:'name','errors')}">
+                                    <input type="text" id="name" name="name" value="${fieldValue(bean:inventoryMovementTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/edit.gsp	(revision 753)
@@ -0,0 +1,93 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit InventoryMovementType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">InventoryMovementType List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New InventoryMovementType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit InventoryMovementType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryMovementTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryMovementTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${inventoryMovementTypeInstance?.id}" />
+                <input type="hidden" name="version" value="${inventoryMovementTypeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementTypeInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:inventoryMovementTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="incrementsInventory">Increments Inventory:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementTypeInstance,field:'incrementsInventory','errors')}">
+                                    <g:checkBox name="incrementsInventory" value="${inventoryMovementTypeInstance?.incrementsInventory}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryMovements">Inventory Movements:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementTypeInstance,field:'inventoryMovements','errors')}">
+                                    
+<ul>
+<g:each var="i" in="${inventoryMovementTypeInstance?.inventoryMovements?}">
+    <li><g:link controller="inventoryMovement" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="inventoryMovement" params="['inventoryMovementType.id':inventoryMovementTypeInstance?.id]" action="create">Add InventoryMovement</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryMovementTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryMovementTypeInstance,field:'name','errors')}">
+                                    <input type="text" id="name" name="name" value="${fieldValue(bean:inventoryMovementTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/list.gsp	(revision 753)
@@ -0,0 +1,59 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>InventoryMovementType List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New InventoryMovementType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>InventoryMovementType List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="incrementsInventory" title="Increments Inventory" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${inventoryMovementTypeInstanceList}" status="i" var="inventoryMovementTypeInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${inventoryMovementTypeInstance.id}">${fieldValue(bean:inventoryMovementTypeInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:inventoryMovementTypeInstance, field:'description')}</td>
+                        
+                            <td>${fieldValue(bean:inventoryMovementTypeInstance, field:'incrementsInventory')}</td>
+                        
+                            <td>${fieldValue(bean:inventoryMovementTypeInstance, field:'isActive')}</td>
+                        
+                            <td>${fieldValue(bean:inventoryMovementTypeInstance, field:'name')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${inventoryMovementTypeInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryMovementType/show.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show InventoryMovementType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">InventoryMovementType List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New InventoryMovementType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show InventoryMovementType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryMovementTypeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryMovementTypeInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Increments Inventory:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryMovementTypeInstance, field:'incrementsInventory')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Inventory Movements:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="i" in="${inventoryMovementTypeInstance.inventoryMovements}">
+                                    <li><g:link controller="inventoryMovement" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryMovementTypeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryMovementTypeInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${inventoryMovementTypeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/create.gsp	(revision 753)
@@ -0,0 +1,73 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create InventoryStore</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryStoreInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryStoreInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryStoreInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:inventoryStoreInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryStoreInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:inventoryStoreInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryStoreInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryStoreInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="site">Site:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryStoreInstance,field:'site','errors')}">
+                                    <g:select optionKey="id" from="${Site.list()}" name="site.id" value="${inventoryStoreInstance?.site?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,93 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit InventoryStore</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryStoreInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryStoreInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${inventoryStoreInstance?.id}" />
+                <input type="hidden" name="version" value="${inventoryStoreInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryStoreInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:inventoryStoreInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryStoreInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:inventoryStoreInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryStoreInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryStoreInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="site">Site:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryStoreInstance,field:'site','errors')}">
+                                    <g:select optionKey="id" from="${Site.list()}" name="site.id" value="${inventoryStoreInstance?.site?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryLocations">Inventory Locations:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryStoreInstance,field:'inventoryLocations','errors')}">
+                                    
+<ul>
+<g:each var="i" in="${inventoryStoreInstance?.inventoryLocations?}">
+    <li><g:link controller="inventoryLocationDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="inventoryLocationDetailed" params="['inventoryStore.id':inventoryStoreInstance?.id]" action="create">+Add Inventory Location</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/list.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>InventoryStore List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                            <g:sortableColumn property="id" title="Id" />
+
+                            <g:sortableColumn property="name" title="Name" />
+
+                            <g:sortableColumn property="description" title="Description" />
+
+                            <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th>Site</th>
+
+                            <th></th>
+                   	    
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${inventoryStoreInstanceList}" status="i" var="inventoryStoreInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryStoreDetailed/show/${inventoryStoreInstance.id}"'>
+                                ${fieldValue(bean:inventoryStoreInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryStoreDetailed/show/${inventoryStoreInstance.id}"'>
+                                ${fieldValue(bean:inventoryStoreInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryStoreDetailed/show/${inventoryStoreInstance.id}"'>
+                                ${fieldValue(bean:inventoryStoreInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryStoreDetailed/show/${inventoryStoreInstance.id}"'>
+                                ${fieldValue(bean:inventoryStoreInstance, field:'isActive')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/inventoryStoreDetailed/show/${inventoryStoreInstance.id}"'>
+                                ${fieldValue(bean:inventoryStoreInstance, field:'site')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${inventoryStoreInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${inventoryStoreInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryStoreDetailed/show.gsp	(revision 753)
@@ -0,0 +1,83 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show InventoryStore</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryStoreInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryStoreInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryStoreInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryStoreInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Site:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="siteDetailed" action="show" id="${inventoryStoreInstance?.site?.id}">${inventoryStoreInstance?.site?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Inventory Locations:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="i" in="${inventoryStoreInstance.inventoryLocations}">
+                                    <li><g:link controller="inventoryLocationDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${inventoryStoreInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryType/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryType/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryType/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create InventoryType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">InventoryType List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create InventoryType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryTypeInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:inventoryTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryTypeInstance,field:'name','errors')}">
+                                    <input type="text" id="name" name="name" value="${fieldValue(bean:inventoryTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryType/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryType/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryType/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit InventoryType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">InventoryType List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New InventoryType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit InventoryType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${inventoryTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${inventoryTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${inventoryTypeInstance?.id}" />
+                <input type="hidden" name="version" value="${inventoryTypeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryTypeInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:inventoryTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryItems">Inventory Items:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryTypeInstance,field:'inventoryItems','errors')}">
+                                    
+<ul>
+<g:each var="i" in="${inventoryTypeInstance?.inventoryItems?}">
+    <li><g:link controller="inventoryItem" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="inventoryItem" params="['inventoryType.id':inventoryTypeInstance?.id]" action="create">Add InventoryItem</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${inventoryTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:inventoryTypeInstance,field:'name','errors')}">
+                                    <input type="text" id="name" name="name" value="${fieldValue(bean:inventoryTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryType/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryType/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryType/list.gsp	(revision 753)
@@ -0,0 +1,55 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>InventoryType List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New InventoryType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>InventoryType List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${inventoryTypeInstanceList}" status="i" var="inventoryTypeInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${inventoryTypeInstance.id}">${fieldValue(bean:inventoryTypeInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:inventoryTypeInstance, field:'description')}</td>
+                        
+                            <td>${fieldValue(bean:inventoryTypeInstance, field:'isActive')}</td>
+                        
+                            <td>${fieldValue(bean:inventoryTypeInstance, field:'name')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${inventoryTypeInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/inventoryType/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/inventoryType/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/inventoryType/show.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show InventoryType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">InventoryType List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New InventoryType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show InventoryType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryTypeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryTypeInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Inventory Items:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="i" in="${inventoryTypeInstance.inventoryItems}">
+                                    <li><g:link controller="inventoryItem" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryTypeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:inventoryTypeInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${inventoryTypeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/layouts/main.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/layouts/main.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/layouts/main.gsp	(revision 753)
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+    <head>
+        <title><g:layoutTitle default="gnuMims" /></title>
+        <link rel="stylesheet" href="${resource(dir:'css',file:'main.css')}" />
+        <link rel="shortcut icon" href="${resource(dir:'images',file:'gnuMimsIcon.ico')}" type="image/x-icon" />
+        <g:javascript library="prototype/prototype" />
+        <g:javascript library="prototype/effects" />
+        <g:javascript library="application" />
+        <g:javascript src="overlayPane.js" />
+        <jsUtil:resources />
+        <gnuMims:resources />
+        <nav:resources override="true"/>
+        <g:helpBalloons icon="${resource(plugin:'help-balloons', dir:'images', file:'balloon-icon.gif')}"
+                                        button="${resource(plugin:'help-balloons', dir:'images', file:'balloon-button.png')}"
+                                        balloonPrefix="${resource(plugin:'help-balloons', dir:'images')}/balloon-"/>
+        <g:layoutHead />
+    </head>
+
+    <!-- Added g:pageProperty so that onload in each page works -->
+    <body onload="${pageProperty(name: 'body.onload')}">
+        <div id="wrapper" style="height: 100%;">
+            <div id="top">
+            </div>
+            <div id="content" align="center">
+                <div id="spinner" class="spinner" style="display:none;">
+                    <img src="${resource(dir:'images',file:'loading_bar.gif')}" alt="Spinner" />
+                </div>
+                <g:if env="production">
+                    <div id="Header">
+                        <a href="http://www.gnumims.org" id=HeaderLink></a>
+                    </div>
+                </g:if>
+                <g:else>
+                    <div id="HeaderDev">
+                        <a href="http://www.gnumims.org" id=HeaderLink></a>
+                    </div>
+                </g:else>
+
+                <g:isLoggedIn>
+                    <div class="appControl">
+                        <g:link controller="logout" class="logoutButton">
+                                Log out (<g:loggedInUsername/>)
+                        </g:link>
+                        <div id="menu">
+                            <nav:render group="nav"/>
+                        </div>
+                        <gnuMims:assetTreeButton />
+                    </div>
+                </g:isLoggedIn>
+
+                <g:layoutBody />
+
+            </div> <!-- content -->
+            <div id="bottom">
+            </div>
+        </div> <!-- wrapper -->
+
+        <!-- Asset Tree Pane -->
+        <gnuMims:assetTreePane />
+
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/login/auth.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/login/auth.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/login/auth.gsp	(revision 753)
@@ -0,0 +1,121 @@
+<head>
+<meta name='layout' content='main' />
+<title>Login</title>
+<style type='text/css' media='screen'>
+#login {
+    margin:15px 0px; padding:0px;
+    text-align:center;
+}
+#login .inner {
+    width:260px;
+    margin:0px auto;
+    text-align:left;
+    padding:10px;
+/*	border-top:1px dashed #499ede;
+    border-bottom:1px dashed #499ede;*/
+/*	background-color:#EEF;*/
+}
+#login .inner .fheader {
+    padding:4px;margin:3px 0px 3px 0;color:#2e3741;font-size:14px;font-weight:bold;
+}
+#login .inner .cssform p {
+    clear: left;
+    margin: 0;
+    padding: 5px 0 0 0;
+    padding-left: 105px;
+/*	border-top: 1px dashed gray;*/
+    margin-bottom: 10px;
+    height: 1%;
+}
+#login .loginButton {
+    float: left;
+    background: #fff url(../images/skin/shadow.jpg) bottom repeat-x;
+    border: 1px solid #ccc;
+    border-color: #ccc #aaa #aaa #ccc;
+    margin: 0;
+}
+#login .inner .cssform input[type='text'] {
+    width: 120px;
+}
+#login .inner .cssform input[type='submit'] {
+    background: transparent url(../images/skin/key_go.png) 5px 50% no-repeat;
+    padding-left: 28px;
+    border: none;
+    cursor: pointer;
+    margin: 0;
+    overflow: hidden;
+}
+#login .inner .cssform input[type='submit']:link {
+}
+#login .inner .cssform input[type='submit']:visited {
+}
+#login .inner .cssform input[type='submit']:hover {
+    /*background: #bfdaff;*/
+}
+#login .inner .cssform input[type='submit']:focus {
+}
+#login .inner .cssform label {
+    font-weight: bold;
+    float: left;
+    margin-left: -105px;
+    width: 100px;
+    padding: 5px 0 0 0;
+}
+#login .inner .login_message {color:red;}
+#login .inner .text_ {width:120px;}
+#login .inner .chk {height:12px;}
+</style>
+</head>
+
+<body>
+    <div id='login'>
+        <h1>Welcome to gnuMims please log in</h1>
+
+        <g:if env="development">
+        The demo users are <b>user</b>, <b>manager</b> and  <b>admin</b> all having the password: <b>pass</b>
+        </g:if>
+
+        <div class='inner'>
+            <g:if test='${flash.message}'>
+            <div class='login_message'>${flash.message}</div>
+            </g:if>
+            <div class='fheader'></div>
+            <form action='${postUrl}' method='POST' id='loginForm' class='cssform'>
+                <p>
+                    <label for='j_username'>Login ID</label>
+
+                    <g:if env="production">
+                        <input type='text' class='text_' name='j_username' id='j_username'/>
+                    </g:if>
+                    <g:else >
+                        <input type='text' class='text_' name='j_username' id='j_username' value='manager'  />
+                    </g:else >
+
+                </p>
+                <p>
+                    <label for='j_password'>Password</label>
+
+                    <g:if env="production">
+                        <input type='password' class='text_' name='j_password' id='j_password' />
+                    </g:if>
+                    <g:else >
+                        <input type='password' class='text_' name='j_password' id='j_password' value="pass" />
+                    </g:else >
+                </p>
+
+                <p>
+                    <span class="loginButton">
+                        <input type='submit' value='Login' />
+                    </span>
+                </p>
+            </form>
+        </div>
+    </div>
+<script type='text/javascript'>
+<!--
+(function(){
+    document.forms['loginForm'].elements['j_username'].focus();
+})();
+// -->
+</script>
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/login/denied.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/login/denied.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/login/denied.gsp	(revision 753)
@@ -0,0 +1,6 @@
+<meta name='layout' content='main' />
+<title>Denied</title>
+
+<div class='body'>
+	<div class='errors'>Sorry, you're not authorized to view this page.</div>
+</div>
Index: branches/features/taskProcedureRework/grails-app/views/login/openIdAuth.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/login/openIdAuth.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/login/openIdAuth.gsp	(revision 753)
@@ -0,0 +1,67 @@
+<head>
+<meta name='layout' content='main' />
+<title>Login</title>
+<style type='text/css' media='screen'>
+#login {
+	margin:15px 0px; padding:0px;
+	text-align:center;
+}
+#login .inner {
+	width:260px;
+	margin:0px auto;
+	text-align:left;
+	padding:10px;
+	border-top:1px dashed #499ede;
+	border-bottom:1px dashed #499ede;
+	background-color:#EEF;
+}
+#login .inner .fheader {
+	padding:4px;margin:3px 0px 3px 0;color:#2e3741;font-size:14px;font-weight:bold;
+}
+#login .inner .cssform p{
+	clear: left;
+	margin: 0;
+	padding: 5px 0 8px 0;
+	padding-left: 105px;
+	border-top: 1px dashed gray;
+	margin-bottom: 10px;
+	height: 1%;
+}
+#login .inner .cssform input[type='text']{ 
+	width: 120px;
+}
+#login .inner .cssform label{
+	font-weight: bold;
+	float: left;
+	margin-left: -105px; 
+	width: 100px;
+}
+#login .inner .login_message {color:red;}
+#login .inner .text_ {width:120px;}
+</style>
+</head>
+
+<body>
+	<div id='login'>
+		<div class='inner'>
+			<g:if test='${flash.message}'>
+			<div class='login_message'>${flash.message}</div>
+			</g:if>
+			<div class='fheader'>Please Login..</div>
+			<form action='${postUrl}' method='POST' id='loginForm' class='cssform'>
+				<p>
+					<label for='j_username'>OpenID Identity</label>
+					<input type='text' class='text_' name='j_username' />
+				</p>
+				<p>
+					<input type='submit' value='Login' />
+				</p>
+			</form>
+		</div>
+	</div>
+<script type='text/javascript'>
+(function(){
+	document.forms['loginForm'].elements['j_username'].focus();
+})();
+</script>
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/maintenanceActionDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/maintenanceActionDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/maintenanceActionDetailed/create.gsp	(revision 753)
@@ -0,0 +1,118 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create MaintenanceAction</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Maintenance Action</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${maintenanceActionInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${maintenanceActionInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="section">Section:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'section','errors')}">
+                                    <g:select optionKey="id" from="${Section.list()}" name="section.id" value="${maintenanceActionInstance?.section?.id}" noSelection="['null':'']"></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="asset">Asset:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'asset','errors')}">
+                                    <g:select optionKey="id" from="${Asset.list()}" name="asset.id" value="${maintenanceActionInstance?.asset?.id}" noSelection="['null':'']"></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="assetSubItem">Asset Sub Item:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'assetSubItem','errors')}">
+                                    <g:select optionKey="id" from="${AssetSubItem.list()}" name="assetSubItem.id" value="${maintenanceActionInstance?.assetSubItem?.id}" noSelection="['null':'']"></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="maintenancePolicy">Maintenance Policy:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'maintenancePolicy','errors')}">
+                                    <g:select optionKey="id" from="${MaintenancePolicy.list()}" name="maintenancePolicy.id" value="${maintenanceActionInstance?.maintenancePolicy?.id}" noSelection="['null':'']"></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="procedureStepNumber">Procedure Step Number:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'procedureStepNumber','errors')}">
+                                    <input type="text" id="procedureStepNumber" name="procedureStepNumber" value="${fieldValue(bean:maintenanceActionInstance,field:'procedureStepNumber')}" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:maintenanceActionInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="reasoning">Reasoning:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'reasoning','errors')}">
+                                    <input type="text" id="reasoning" name="reasoning" value="${fieldValue(bean:maintenanceActionInstance,field:'reasoning')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${maintenanceActionInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskProcedure">Task Procedure:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'taskProcedure','errors')}">
+                                    <g:select optionKey="id" from="${TaskProcedure.list()}" name="taskProcedure.id" value="${maintenanceActionInstance?.taskProcedure?.id}" ></g:select>
+                                    <p><g:link controller="taskProcedureDetailed" action="create">+Add Task Procedure</g:link></p>
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/maintenanceActionDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/maintenanceActionDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/maintenanceActionDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,120 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit MaintenanceAction</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Maintenance Action</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${maintenanceActionInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${maintenanceActionInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${maintenanceActionInstance?.id}" />
+                <input type="hidden" name="version" value="${maintenanceActionInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="section">Section:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'section','errors')}">
+                                    <g:select optionKey="id" from="${Section.list()}" name="section.id" value="${maintenanceActionInstance?.section?.id}" noSelection="['null':'']"></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="asset">Asset:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'asset','errors')}">
+                                    <g:select optionKey="id" from="${Asset.list()}" name="asset.id" value="${maintenanceActionInstance?.asset?.id}" noSelection="['null':'']"></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="assetSubItem">Asset Sub Item:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'assetSubItem','errors')}">
+                                    <g:select optionKey="id" from="${AssetSubItem.list()}" name="assetSubItem.id" value="${maintenanceActionInstance?.assetSubItem?.id}" noSelection="['null':'']"></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="maintenancePolicy">Maintenance Policy:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'maintenancePolicy','errors')}">
+                                    <g:select optionKey="id" from="${MaintenancePolicy.list()}" name="maintenancePolicy.id" value="${maintenanceActionInstance?.maintenancePolicy?.id}" noSelection="['null':'']"></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="procedureStepNumber">Procedure Step Number:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'procedureStepNumber','errors')}">
+                                    <input type="text" id="procedureStepNumber" name="procedureStepNumber" value="${fieldValue(bean:maintenanceActionInstance,field:'procedureStepNumber')}" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:maintenanceActionInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="reasoning">Reasoning:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'reasoning','errors')}">
+                                    <input type="text" id="reasoning" name="reasoning" value="${fieldValue(bean:maintenanceActionInstance,field:'reasoning')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${maintenanceActionInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskProcedure">Task Procedure:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenanceActionInstance,field:'taskProcedure','errors')}">
+                                    <g:select optionKey="id" from="${TaskProcedure.list()}" name="taskProcedure.id" value="${maintenanceActionInstance?.taskProcedure?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/maintenanceActionDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/maintenanceActionDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/maintenanceActionDetailed/show.gsp	(revision 753)
@@ -0,0 +1,104 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show MaintenanceAction</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Maintenance Action</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:maintenanceActionInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Section:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="sectionDetailed" action="show" id="${maintenanceActionInstance?.section?.id}">${maintenanceActionInstance?.section?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Asset:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="assetDetailed" action="show" id="${maintenanceActionInstance?.asset?.id}">${maintenanceActionInstance?.asset?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Asset Sub Item:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="assetSubItemDetailed" action="show" id="${maintenanceActionInstance?.assetSubItem?.id}">${maintenanceActionInstance?.assetSubItem?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Maintenance Policy:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="maintenancePolicyDetailed" action="show" id="${maintenanceActionInstance?.maintenancePolicy?.id}">${maintenanceActionInstance?.maintenancePolicy?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Procedure Step Number:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:maintenanceActionInstance, field:'procedureStepNumber')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:maintenanceActionInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Reasoning:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:maintenanceActionInstance, field:'reasoning')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:maintenanceActionInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Task Procedure:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="taskProcedureDetailed" action="show" id="${maintenanceActionInstance?.taskProcedure?.id}">${maintenanceActionInstance?.taskProcedure?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${maintenanceActionInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create MaintenancePolicy</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${maintenancePolicyInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${maintenancePolicyInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenancePolicyInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:maintenancePolicyInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenancePolicyInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:maintenancePolicyInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenancePolicyInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${maintenancePolicyInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,68 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit MaintenancePolicy</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${maintenancePolicyInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${maintenancePolicyInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${maintenancePolicyInstance?.id}" />
+                <input type="hidden" name="version" value="${maintenancePolicyInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenancePolicyInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:maintenancePolicyInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenancePolicyInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:maintenancePolicyInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:maintenancePolicyInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${maintenancePolicyInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/list.gsp	(revision 753)
@@ -0,0 +1,70 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>MaintenancePolicy List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                            <g:sortableColumn property="id" title="Id" />
+
+                            <g:sortableColumn property="name" title="Name" />
+
+                            <g:sortableColumn property="description" title="Description" />
+
+                            <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${maintenancePolicyInstanceList}" status="i" var="maintenancePolicyInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/maintenancePolicyDetailed/show/${maintenancePolicyInstance.id}"'>
+                                ${fieldValue(bean:maintenancePolicyInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/maintenancePolicyDetailed/show/${maintenancePolicyInstance.id}"'>
+                                ${fieldValue(bean:maintenancePolicyInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/maintenancePolicyDetailed/show/${maintenancePolicyInstance.id}"'>
+                                ${fieldValue(bean:maintenancePolicyInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/maintenancePolicyDetailed/show/${maintenancePolicyInstance.id}"'>
+                                ${fieldValue(bean:maintenancePolicyInstance, field:'isActive')}
+                            </td>
+                            
+                            <td class="notClickable">
+                                <g:link action="show" id="${maintenancePolicyInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${maintenancePolicyInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/maintenancePolicyDetailed/show.gsp	(revision 753)
@@ -0,0 +1,63 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show MaintenancePolicy</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:maintenancePolicyInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:maintenancePolicyInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:maintenancePolicyInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:maintenancePolicyInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${maintenancePolicyInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/period/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/period/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/period/create.gsp	(revision 753)
@@ -0,0 +1,55 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Period</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">Period List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create Period</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${periodInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${periodInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:periodInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${periodInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="period">Period:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:periodInstance,field:'period','errors')}">
+                                    <input type="text" id="period" name="period" value="${fieldValue(bean:periodInstance,field:'period')}"/>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/period/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/period/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/period/edit.gsp	(revision 753)
@@ -0,0 +1,75 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit Period</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">Period List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New Period</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit Period</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${periodInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${periodInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${periodInstance?.id}" />
+                <input type="hidden" name="version" value="${periodInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:periodInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${periodInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="period">Period:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:periodInstance,field:'period','errors')}">
+                                    <input type="text" id="period" name="period" value="${fieldValue(bean:periodInstance,field:'period')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskRecurringSchedules">Task Recurring Schedules:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:periodInstance,field:'taskRecurringSchedules','errors')}">
+                                    
+<ul>
+<g:each var="t" in="${periodInstance?.taskRecurringSchedules?}">
+    <li><g:link controller="taskRecurringSchedule" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="taskRecurringSchedule" params="['period.id':periodInstance?.id]" action="create">Add TaskRecurringSchedule</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/period/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/period/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/period/list.gsp	(revision 753)
@@ -0,0 +1,51 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Period List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New Period</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Period List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                   	        <g:sortableColumn property="period" title="Period" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${periodInstanceList}" status="i" var="periodInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${periodInstance.id}">${fieldValue(bean:periodInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:periodInstance, field:'isActive')}</td>
+                        
+                            <td>${fieldValue(bean:periodInstance, field:'period')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${periodInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/period/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/period/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/period/show.gsp	(revision 753)
@@ -0,0 +1,70 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show Period</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">Period List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New Period</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show Period</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:periodInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:periodInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Period:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:periodInstance, field:'period')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Task Recurring Schedules:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="t" in="${periodInstance.taskRecurringSchedules}">
+                                    <li><g:link controller="taskRecurringSchedule" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${periodInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/person/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/person/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/person/create.gsp	(revision 753)
@@ -0,0 +1,152 @@
+<head>
+    <meta name="layout" content="main" />
+    <title>Create Person</title>
+    <nav:resources override="true"/>
+</head>
+
+<body>
+
+    <div class="nav">
+        <nav:renderSubItems group="navAlt"/>
+    </div>
+
+    <div class="body">
+        <g:render template="/shared/messages" />
+        <g:hasErrors bean="${person}">
+        <div class="errors">
+            <g:renderErrors bean="${person}" as="list" />
+        </div>
+        </g:hasErrors>
+        <g:form action="save">
+            <div class="dialog">
+                <table>
+                <tbody>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="loginName">Login Name:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'loginName','errors')}">
+                            <input type="text" id="loginName" name="loginName" value="${person.loginName?.encodeAsHTML()}"/>
+                            <g:helpBalloon class="helpballoon" code="person.loginName" />
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="firstName">First Name:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'firstName','errors')}">
+                            <input type="text" id="firstName" name="firstName" value="${person.firstName?.encodeAsHTML()}"/>
+                            <g:helpBalloon class="helpballoon" code="person.firstName" />
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="lastName">Last Name:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'lastName','errors')}">
+                            <input type="text" id="lastName" name="lastName" value="${person.lastName?.encodeAsHTML()}"/>
+                            <g:helpBalloon class="helpballoon" code="person.lastName" />
+                        </td>
+                    </tr>
+
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="pass">Password:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'pass','errors')}">
+                            <input type="password" id="pass" name="pass"/>
+                            <g:helpBalloon class="helpballoon" code="person.password" />
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="isActive">Active:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'isActive','errors')}">
+                            <g:checkBox name="isActive" value="${person.isActive}" ></g:checkBox>
+                            <g:helpBalloon class="helpballoon" code="person.isActive" />
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="description">Description:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'description','errors')}">
+                            <input type="text" id="description" name="description" value="${person.description?.encodeAsHTML()}"/>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="employeeID">employee ID:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'employeeID','errors')}">
+                            <input type="text" id="employeeID" name="employeeID" value="${person.employeeID?.encodeAsHTML()}"/>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name">
+                            <label for="department">Department:</label>
+                        </td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'department','errors')}">
+                            <g:select optionKey="id" from="${Department.list()}" name="department.id" value="${person?.department?.id}" noSelection="['null':'--None--']"></g:select>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name">
+                            <label for="personGroups">Groups:</label>
+                        </td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'personGroups','errors')}">
+                            <g:helpBalloon class="helpballoon" code="person.personGroups" />
+                            <custom:checkBoxList name="personGroups"
+                                                            from="${PersonGroup.findAllByIsActive(true)}"
+                                                            value="${person?.personGroups?.collect{it.id}}"
+                                                            optionKey="id"
+                                                            sortBy="name"
+                                                            linkController="personGroupDetailed"
+                                                            linkAction="show"/>
+                            <g:link controller="personGroupDetailed" action="create">+Add Group</g:link>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name">
+                            <label for="purchasingGroups">Purchasing Groups:</label>
+                        </td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'purchasingGroups','errors')}">
+                            <g:helpBalloon class="helpballoon" code="person.purchasingGroups" />
+                            <custom:checkBoxList name="purchasingGroups"
+                                                            from="${PurchasingGroup.findAllByIsActive(true)}"
+                                                            value="${person?.purchasingGroups?.collect{it.id}}"
+                                                            optionKey="id"
+                                                            sortBy="name"
+                                                            linkController="purchasingGroupDetailed"
+                                                            linkAction="show"/>
+                            <g:link controller="purchasingGroupDetailed" action="create">+Add Group</g:link>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name" align="left">
+                            Authorities:
+                        </td>
+                        <td valign="top" class="name" align="left">
+                            <g:helpBalloon class="helpballoon" code="person.authorities" />
+                        </td>
+                    </tr>
+
+                    <g:each in="${authorityList}">
+                    <tr>
+                        <td valign="top" class="name" align="left">${it.description.encodeAsHTML()}</td>
+                        <td align="left">
+                            <g:checkBox name="${it.authority}" value="${it.authority == 'ROLE_AppUser'}"/>
+                        </td>
+                    </tr>
+                    </g:each>
+
+                </tbody>
+                </table>
+            </div>
+
+            <div class="buttons">
+                <span class="button"><input class="save" type="submit" value="Create" /></span>
+            </div>
+
+        </g:form>
+
+    </div>
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/person/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/person/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/person/edit.gsp	(revision 753)
@@ -0,0 +1,191 @@
+<head>
+    <meta name="layout" content="main" />
+    <title>Edit Person</title>
+    <nav:resources override="true"/>
+</head>
+
+<body>
+
+    <div class="nav">
+        <nav:renderSubItems group="navAlt"/>
+    </div>
+
+    <div class="body">
+        <g:render template="/shared/messages" />
+        <g:hasErrors bean="${person}">
+        <div class="errors">
+            <g:renderErrors bean="${person}" as="list" />
+        </div>
+        </g:hasErrors>
+
+    <!--<div class="prop">
+            <span class="name">ID: ${person.id}</span>
+        </div>-->
+
+        <g:form>
+            <input type="hidden" name="id" value="${person.id}" />
+            <input type="hidden" name="version" value="${person.version}" />
+            <input type="hidden" name="password" value="${person.password}" />
+            <div class="dialog">
+                <table>
+                <tbody>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="loginName">Login Name:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'loginName','errors')}">
+                            <input type="text" id="loginName" name="loginName" value="${person.loginName?.encodeAsHTML()}"/>
+                            <g:helpBalloon class="helpballoon" code="person.loginName" />
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="firstName">First Name:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'firstName','errors')}">
+                            <input type="text" id="firstName" name="firstName" value="${person.firstName?.encodeAsHTML()}"/>
+                            <g:helpBalloon class="helpballoon" code="person.firstName" />
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="lastName">Last Name:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'lastName','errors')}">
+                            <input type="text" id="lastName" name="lastName" value="${person.lastName?.encodeAsHTML()}"/>
+                            <g:helpBalloon class="helpballoon" code="person.lastName" />
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="pass">Password:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'pass','errors')}">
+                            <input type="password" id="pass" name="pass"  value="${person.pass?.encodeAsHTML()}"/>
+                            <g:helpBalloon class="helpballoon" code="person.password" />
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="isActive">Active:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'isActive','errors')}">
+                            <g:checkBox name="isActive" value="${person.isActive}"/>
+                            <g:helpBalloon class="helpballoon" code="person.isActive" />
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="description">Description:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'description','errors')}">
+                            <input type="text" id="description" name="description" value="${person.description?.encodeAsHTML()}"/>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name">
+                            <label for="addresses">Contact:</label>
+                        </td>
+                        <td valign="top" class="value">
+                            <ul>
+                            <g:each var="i" in="${person?.contacts}">
+                                <li><g:link controller="contactDetailed" action="show" id="${i.id}">
+                                    ${i?.encodeAsHTML()}
+                                </g:link></li>
+                            </g:each>
+                            </ul>
+                            <g:link controller="contactDetailed" params="['person.id':person?.id]" action="create">+Add Contact</g:link>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name">
+                            <label for="addresses">Addresses:</label>
+                        </td>
+                        <td valign="top" class="value">
+                            <ul>
+                            <g:each var="i" in="${person?.addresses}">
+                                <li><g:link controller="addressDetailed" action="show" id="${i.id}">
+                                    ${i?.encodeAsHTML()}
+                                </g:link></li>
+                            </g:each>
+                            </ul>
+                            <g:link controller="addressDetailed" params="['person.id':person?.id]" action="create">+Add Address</g:link>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name"><label for="employeeID">employee ID:</label></td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'employeeID','errors')}">
+                            <input type="text" id="employeeID" name="employeeID" value="${person.employeeID?.encodeAsHTML()}"/>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name">
+                            <label for="department">Department:</label>
+                        </td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'department','errors')}">
+                            <g:select optionKey="id" from="${Department.list()}" name="department.id" value="${person?.department?.id}" noSelection="['null':'--None--']"></g:select>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name">
+                            <label for="personGroups">Groups:</label>
+                        </td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'personGroups','errors')}">
+                            <g:helpBalloon class="helpballoon" code="person.personGroups" />
+                            <custom:checkBoxList name="personGroups"
+                                                            from="${PersonGroup.findAllByIsActive(true)}"
+                                                            value="${person?.personGroups?.collect{it.id}}"
+                                                            optionKey="id"
+                                                            sortBy="name"
+                                                            linkController="personGroupDetailed"
+                                                            linkAction="show"/>
+                            <g:link controller="personGroupDetailed" action="create">+Add Group</g:link>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name">
+                            <label for="purchasingGroups">Purchasing Groups:</label>
+                        </td>
+                        <td valign="top" class="value ${hasErrors(bean:person,field:'purchasingGroups','errors')}">
+                            <g:helpBalloon class="helpballoon" code="person.purchasingGroups" />
+                            <custom:checkBoxList name="purchasingGroups"
+                                                            from="${PurchasingGroup.findAllByIsActive(true)}"
+                                                            value="${person?.purchasingGroups?.collect{it.id}}"
+                                                            optionKey="id"
+                                                            sortBy="name"
+                                                            linkController="purchasingGroupDetailed"
+                                                            linkAction="show"/>
+                            <g:link controller="purchasingGroupDetailed" action="create">+Add Group</g:link>
+                        </td>
+                    </tr>
+
+                    <tr class="prop">
+                        <td valign="top" class="name" align="left">
+                            Authorities:
+                        </td>
+                        <td valign="top" class="name" align="left">
+                            <g:helpBalloon class="helpballoon" code="person.authorities" />
+                        </td>
+                    </tr>
+
+                    <g:each var="entry" in="${roleMap}">
+                    <tr>
+                        <td valign="top" class="name" align="left">${entry.key.description.encodeAsHTML()}</td>
+                        <td align="left"><g:checkBox name="${entry.key.authority}" value="${entry.value}"/></td>
+                    </tr>
+                    </g:each>
+
+                </tbody>
+                </table>
+            </div>
+
+            <div class="buttons">
+                <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+            </div>
+
+        </g:form>
+
+    </div>
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/person/importPersons.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/person/importPersons.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/person/importPersons.gsp	(revision 753)
@@ -0,0 +1,35 @@
+<html>
+    <head>
+        <meta name="layout" content="main" />
+        <title>Import Persons</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Import Persons</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:uploadForm action="importPersonsSave" onsubmit="return Lightbox.loading();">
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="file">File:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <input type="file" id="file" name="file" size="40"/>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:uploadForm>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/person/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/person/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/person/list.gsp	(revision 753)
@@ -0,0 +1,133 @@
+<head>
+    <meta name="layout" content="main" />
+    <title>Person List</title>
+    <filterpane:includes />
+    <nav:resources override="true"/>
+</head>
+
+<body>
+
+    <div class="nav">
+        <nav:renderSubItems group="navAlt"/>
+    </div>
+
+    <div class="body">
+        <g:if test="${flash.message}">
+        <div class="message">${flash.message}</div>
+        </g:if>
+        <filterpane:currentCriteria domainBean="Person"
+                                action="list"
+                                dateFormat="EEE, dd-MMM-yyyy"
+                                removeImgDir="images" 
+                                removeImgFile="bullet_delete.png"
+                                title="Search"/>
+
+        <div class="paginateButtons">
+            Results: ${personList.size()} / ${personTotal}
+            <span class="searchButtons">
+                <filterpane:filterButton text="Search" appliedText="Change Search" />
+            </span>
+        </div>
+
+        <jsUtil:toggleControl toggleId="options"
+                                                imageId="optionsImg"
+                                                closedImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_right.png')}"
+                                                openImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_down.png')}"
+                                                text="${g.message(code: 'default.options.text')}"
+                                                />
+
+        <div id="options" style="display:none;">
+            <g:form method="post" >
+                <g:hiddenField name="params" value="${filterParams}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="max">Persons:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:link action="exportPersonsTemplate">
+                                        Template
+                                    </g:link>
+                                    /
+                                    <g:link action="importPersons">
+                                        Import
+                                    </g:link>
+                                </td>
+                            </tr>
+
+                        </tbody>
+                    </table>
+                </div>
+            </g:form>
+        </div>
+
+        <br />
+
+        <g:if test="${personList.size() > 0}">
+            <div class="list">
+                <table>
+                <thead>
+                    <tr>
+                        <g:sortableColumn property="id" title="Id" params="${filterParams}" />
+                        <g:sortableColumn property="loginName" title="Login Name" params="${filterParams}" />
+                        <g:sortableColumn property="firstName" title="First Name" params="${filterParams}" />
+                        <g:sortableColumn property="lastName" title="Last Name" params="${filterParams}" />
+                        <g:sortableColumn property="isActive" title="Active" params="${filterParams}" />
+                        <th></th>
+                    </tr>
+                </thead>
+                <tbody>
+                <g:each in="${personList}" status="i" var="person">
+                    <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                        <td onclick='window.location = "${request.getContextPath()}/person/show/${person.id}"'>
+                            ${person.id}
+                        </td>
+
+                        <td onclick='window.location = "${request.getContextPath()}/person/show/${person.id}"'>
+                            ${person.loginName?.encodeAsHTML()}
+                        </td>
+
+                        <td onclick='window.location = "${request.getContextPath()}/person/show/${person.id}"'>
+                            ${person.firstName?.encodeAsHTML()}
+                        </td>
+
+                        <td onclick='window.location = "${request.getContextPath()}/person/show/${person.id}"'>
+                            ${person.lastName?.encodeAsHTML()}
+                        </td>
+
+                        <td onclick='window.location = "${request.getContextPath()}/person/show/${person.id}"'>
+                            ${person.isActive?.encodeAsHTML()}
+                        </td>
+
+                        <td class="notClickable">
+                            <g:link action="show" id="${person.id}">
+                                <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                            </g:link>
+                        </td>
+                    </tr>
+                </g:each>
+                </tbody>
+                </table>
+            </div>
+        </g:if>
+
+        <div class="paginateButtons">
+            <g:paginate total="${personTotal}" params="${filterParams}" />
+        </div>
+
+        <filterpane:filterPane domainBean="Person"
+                                title="Search"
+                                action="list"
+                                class="overlayPane"
+                                excludeProperties="password, sessionTimeout"
+                                associatedProperties="authorities.authority, personGroups.name"
+                                    filterPropertyValues="${['personGroups.name':[values:PersonGroup.list()],
+                                                                                'authorities.authority':[values:Authority.list()]]}" />
+
+
+    </div> <!-- end body div -->
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/person/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/person/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/person/show.gsp	(revision 753)
@@ -0,0 +1,143 @@
+<head>
+    <meta name="layout" content="main" />
+    <title>Show Person</title>
+    <nav:resources override="true"/>
+</head>
+
+<body>
+
+    <div class="nav">
+        <nav:renderSubItems group="navAlt"/>
+    </div>
+
+    <div class="body">
+        <g:render template="/shared/messages" />
+        <div class="dialog">
+            <table>
+            <tbody>
+
+                <tr class="prop">
+                    <td valign="top" class="name">ID:</td>
+                    <td valign="top" class="value">${person.id}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Login Name:</td>
+                    <td valign="top" class="value">${person.loginName?.encodeAsHTML()}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">First Name:</td>
+                    <td valign="top" class="value">${person.firstName?.encodeAsHTML()}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Last Name:</td>
+                    <td valign="top" class="value">${person.lastName?.encodeAsHTML()}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Active:</td>
+                    <td valign="top" class="value">${person.isActive}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Description:</td>
+                    <td valign="top" class="value">${person.description?.encodeAsHTML()}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Contact:</td>
+
+                    <td  valign="top" class="value">
+                        <ul>
+                        <g:each var="i" in="${person.contacts}">
+                            <li><g:link controller="contactDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                        </g:each>
+                        </ul>
+                    </td>
+
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Addresses:</td>
+
+                    <td  valign="top" class="value">
+                        <ul>
+                        <g:each var="i" in="${person.addresses}">
+                            <li><g:link controller="addressDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                        </g:each>
+                        </ul>
+                    </td>
+
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Employee ID:</td>
+                    <td valign="top" class="value">${person.employeeID}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Department:</td>
+                    <td valign="top" class="value">${person.department}</td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Groups:</td>
+                    <td valign="top" class="value">
+                        <ul>
+                        <g:each var='group' in="${ person.personGroups.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
+                            <li>
+                                <g:link controller="personGroupDetailed"
+                                                action="show"
+                                                id="${group.id}">
+                                    ${group.encodeAsHTML()}
+                                </g:link>
+                            </li>
+                        </g:each>
+                        </ul>
+                    </td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Purchasing Groups:</td>
+                    <td valign="top" class="value">
+                        <ul>
+                        <g:each  var='a' in="${ person.purchasingGroups.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
+                            <li>
+                                <g:link controller="purchasingGroupDetailed"
+                                                action="show"
+                                                id="${a.id}">
+                                    ${a.encodeAsHTML()}
+                                </g:link>
+                            </li>
+                        </g:each>
+                        </ul>
+                    </td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Authorities:</td>
+                    <td valign="top" class="value">
+                        <ul>
+                        <g:each  var='a' in="${authorityList}">
+                            <li>${a.description.encodeAsHTML()}</li>
+                        </g:each>
+                        </ul>
+                    </td>
+                </tr>
+
+            </tbody>
+            </table>
+        </div>
+
+        <div class="buttons">
+            <g:form>
+                <input type="hidden" name="id" value="${person.id}" />
+                <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+            </g:form>
+        </div>
+
+    </div>
+</body>
Index: branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/create.gsp	(revision 753)
@@ -0,0 +1,73 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create PersonGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${personGroupInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${personGroupInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:personGroupInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:personGroupInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${personGroupInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="personGroupType">Person Group Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupInstance,field:'personGroupType','errors')}">
+                                    <g:select optionKey="id" from="${PersonGroupType.list()}" name="personGroupType.id" value="${personGroupInstance?.personGroupType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit PersonGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${personGroupInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${personGroupInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${personGroupInstance?.id}" />
+                <input type="hidden" name="version" value="${personGroupInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:personGroupInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:personGroupInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${personGroupInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="personGroupType">Person Group Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupInstance,field:'personGroupType','errors')}">
+                                    <g:select optionKey="id" from="${PersonGroupType.list()}" name="personGroupType.id" value="${personGroupInstance?.personGroupType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/list.gsp	(revision 753)
@@ -0,0 +1,71 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>PersonGroup List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                            <g:sortableColumn property="personGroupType" title="Group Type" />
+
+                            <th></th>
+                   	    
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${personGroupInstanceList}" status="i" var="personGroupInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/personGroupDetailed/show/${personGroupInstance.id}"'>
+                                ${fieldValue(bean:personGroupInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/personGroupDetailed/show/${personGroupInstance.id}"'>
+                                ${fieldValue(bean:personGroupInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/personGroupDetailed/show/${personGroupInstance.id}"'>
+                                ${fieldValue(bean:personGroupInstance, field:'isActive')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/personGroupDetailed/show/${personGroupInstance.id}"'>
+                                ${fieldValue(bean:personGroupInstance, field:'personGroupType')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${personGroupInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${personGroupInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/personGroupDetailed/show.gsp	(revision 753)
@@ -0,0 +1,83 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show PersonGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:personGroupInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:personGroupInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:personGroupInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:personGroupInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Person Group Type:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="personGroupTypeDetailed" action="show" id="${personGroupInstance?.personGroupType?.id}">${personGroupInstance?.personGroupType?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Persons:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="p" in="${personGroupInstance.persons}">
+                                    <li><g:link controller="person" action="show" id="${p.id}">${p?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${personGroupInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create PersonGroupType</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${personGroupTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${personGroupTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupTypeInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:personGroupTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupTypeInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:personGroupTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${personGroupTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit PersonGroupType</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${personGroupTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${personGroupTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${personGroupTypeInstance?.id}" />
+                <input type="hidden" name="version" value="${personGroupTypeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupTypeInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:personGroupTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupTypeInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:personGroupTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${personGroupTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="personGroups">Person Groups:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:personGroupTypeInstance,field:'personGroups','errors')}">
+                                    
+<ul>
+<g:each var="p" in="${personGroupTypeInstance?.personGroups?}">
+    <li><g:link controller="personGroupDetailed" action="show" id="${p.id}">${p?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="personGroupDetailed" params="['personGroupType.id':personGroupTypeInstance?.id]" action="create">+Add PersonGroup</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/list.gsp	(revision 753)
@@ -0,0 +1,71 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>PersonGroupType List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${personGroupTypeInstanceList}" status="i" var="personGroupTypeInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/personGroupTypeDetailed/show/${personGroupTypeInstance.id}"'>
+                                ${fieldValue(bean:personGroupTypeInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/personGroupTypeDetailed/show/${personGroupTypeInstance.id}"'>
+                                ${fieldValue(bean:personGroupTypeInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/personGroupTypeDetailed/show/${personGroupTypeInstance.id}"'>
+                                ${fieldValue(bean:personGroupTypeInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/personGroupTypeDetailed/show/${personGroupTypeInstance.id}"'>
+                                ${fieldValue(bean:personGroupTypeInstance, field:'isActive')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${personGroupTypeInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${personGroupTypeInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/personGroupTypeDetailed/show.gsp	(revision 753)
@@ -0,0 +1,76 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show PersonGroupType</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:personGroupTypeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:personGroupTypeInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:personGroupTypeInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:personGroupTypeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Person Groups:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="p" in="${personGroupTypeInstance.personGroups}">
+                                    <li><g:link controller="personGroupDetailed" action="show" id="${p.id}">${p?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${personGroupTypeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/pictureDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/pictureDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/pictureDetailed/create.gsp	(revision 753)
@@ -0,0 +1,49 @@
+<html>
+    <head>
+        <meta name="layout" content="main" />
+        <title>Create Picture</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Picture</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${picture}">
+                <div class="errors">
+                    <g:renderErrors bean="${picture}" as="list" />
+                </div>
+            </g:hasErrors>
+            <g:uploadForm action="save" onsubmit="return Lightbox.loading();">
+                <g:hiddenField name="inventoryItem.id" value="${picture.inventoryItem.id}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryItem.id">Inventory Item:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    ${picture.inventoryItem}
+                                </td>
+                            </tr> 
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="file">File:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean: picture, field: 'file', 'errors')}">
+                                    <input type="file" id="file" name="file" size="40"/>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:uploadForm>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/pictureDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/pictureDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/pictureDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,66 @@
+<html>
+    <head>
+        <meta name="layout" content="main" />
+        <title>Edit Picture</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Picture</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${picture}">
+                <div class="errors">
+                    <g:renderErrors bean="${picture}" as="list" />
+                </div>
+            </g:hasErrors>
+            <g:form method="post" onsubmit="return Lightbox.loading();">
+                <input type="hidden" name="id" value="${picture?.id}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                            <tr class="prop">
+                                <td valign="top" class="name">Picture:</td>
+                                <td valign="top" class="value">
+                                    <span class='gallery'><wa:pictureLightboxAnchor picture="${picture}" size="${Image.Medium}" lightboxSize="${Image.Large}" title="Slide Show" /></span>
+                                </td>
+                            </tr>
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="operation">Operation:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean: picture, field: 'operation', 'errors')}">
+                                    <select id="operation" name="operation">
+                                        <option value="${Picture.NoOp}" selected="selected">None</option>
+                                        <option value="${Picture.RotateClockWise90}">Rotate clockwise 90 degrees</option>
+                                        <option value="${Picture.RotateAntiClockWise90}">Rotate anti-clockwise 90 degrees</option>
+                                        <option value="${Picture.Rotate180}">Rotate 180 degrees</option>
+                                        <option value="${Picture.Flip}">Vertical mirror image</option>
+                                        <option value="${Picture.Flop}">Horizontal mirror image</option>
+                                    </select>
+                                </td>
+                            </tr>
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryItem.id">Inventory Item:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:link controller="inventoryItemDetailed" action="show" id="${picture.inventoryItem?.id}" title="Show Inventory Item">
+                                        ${picture.inventoryItem?.toString()?.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/pictureDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/pictureDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/pictureDetailed/list.gsp	(revision 753)
@@ -0,0 +1,64 @@
+<html>
+    <head>
+        <meta name="layout" content="main" />
+        <title>Picture List</title>
+        <nav:resources override="true"/>
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Picture List</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                            <th>Picture</th>
+                            <g:sortableColumn property="inventoryItem" title="Inventory Item" />
+                            <g:sortableColumn property="dateCreated" title="Date Created" />
+                            <g:sortableColumn property="lastUpdated" title="Last Updated" />
+                            <th></th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        <g:each in="${list}" status="i" var="picture">
+                            <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}">
+                                <td class="notClickable">
+                                    <wa:pictureLightboxAnchor picture="${picture}"
+                                                                                        size="${Image.Small}"
+                                                                                        lightboxSize="${Image.Large}"
+                                                                                        target="_blank" title="Show Original" />
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/pictureDetailed/show/${picture.id}"' >
+                                    <g:link controller="inventoryItemDetailed" action="show" id="${picture.inventoryItem?.id}" title="Show Inventory Item">
+                                        ${picture.inventoryItem?.toString()?.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/pictureDetailed/show/${picture.id}"' >
+                                    <g:formatDate format="EEE, dd-MMM-yyyy" date="${picture.dateCreated}"/>
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/pictureDetailed/show/${picture.id}"' >
+                                    <g:formatDate format="EEE, dd-MMM-yyyy" date="${picture.lastUpdated}"/>
+                                </td>
+
+                                <td class="notClickable">
+                                    <g:link action="show" id="${picture.id}">
+                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                    </g:link>
+                                </td>
+                            </tr>
+                        </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${paginateCount}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/pictureDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/pictureDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/pictureDetailed/show.gsp	(revision 753)
@@ -0,0 +1,54 @@
+<html>
+    <head>
+        <meta name="layout" content="main" />
+        <title>Show Picture</title>
+        <g:render template="/shared/pictureHead" />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Picture</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+                        <tr class="prop">
+                            <td valign="top" class="name">Picture:</td>
+                            <td valign="top" class="value">
+                                <span class='gallery'><wa:pictureLightboxAnchor picture="${picture}" size="${Image.Medium}" lightboxSize="${Image.Large}" target="_blank" title="Show Original" /></span>
+                            </td>
+                        </tr>
+                        <tr class="prop">
+                            <td valign="top" class="name">Inventory Item:</td>
+                            <td valign="top" class="value"><g:link controller="inventoryItemDetailed" action="show" id="${picture.inventoryItem?.id}" title="Show Inventory Item">${picture.inventoryItem?.toString()?.encodeAsHTML()}</g:link></td>
+                        </tr>
+                        <tr class="prop">
+                            <td valign="top" class="name">Height:</td>
+                            <td valign="top" class="value">${picture.height}</td>
+                        </tr>
+                        <tr class="prop">
+                            <td valign="top" class="name">Width:</td>
+                            <td valign="top" class="value">${picture.width}</td>
+                        </tr>
+                        <tr class="prop">
+                            <td valign="top" class="name">Date Created:</td>
+                            <td valign="top" class="value"><g:formatDate format="EEE, dd-MMM-yyyy" date="${picture.dateCreated}"/></td>
+                        </tr>
+                        <tr class="prop">
+                            <td valign="top" class="name">Last Updated:</td>
+                            <td valign="top" class="value"><g:formatDate format="EEE, dd-MMM-yyyy" date="${picture.lastUpdated}"/></td>
+                        </tr>
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${picture?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/create.gsp	(revision 753)
@@ -0,0 +1,62 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create ProductionReference</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${productionReferenceInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${productionReferenceInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:productionReferenceInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:productionReferenceInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:productionReferenceInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="75" id="description" name="description" value="${fieldValue(bean:productionReferenceInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:productionReferenceInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${productionReferenceInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,66 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit ProductionReference</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${productionReferenceInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${productionReferenceInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${productionReferenceInstance?.id}" />
+                <input type="hidden" name="version" value="${productionReferenceInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:productionReferenceInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:productionReferenceInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:productionReferenceInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="75" id="description" name="description" value="${fieldValue(bean:productionReferenceInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:productionReferenceInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${productionReferenceInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/list.gsp	(revision 753)
@@ -0,0 +1,69 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>ProductionReference List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${productionReferenceInstanceList}" status="i" var="productionReferenceInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/productionReferenceDetailed/show/${productionReferenceInstance.id}"'>
+                                ${fieldValue(bean:productionReferenceInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/productionReferenceDetailed/show/${productionReferenceInstance.id}"'>
+                                ${fieldValue(bean:productionReferenceInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/productionReferenceDetailed/show/${productionReferenceInstance.id}"'>
+                                ${fieldValue(bean:productionReferenceInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/productionReferenceDetailed/show/${productionReferenceInstance.id}"'>
+                                ${fieldValue(bean:productionReferenceInstance, field:'isActive')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${productionReferenceInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${productionReferenceInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/productionReferenceDetailed/show.gsp	(revision 753)
@@ -0,0 +1,61 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show ProductionReference</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:productionReferenceInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:productionReferenceInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:productionReferenceInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:productionReferenceInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${productionReferenceInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/create.gsp	(revision 753)
@@ -0,0 +1,62 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create PurchasingGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${purchasingGroupInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${purchasingGroupInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:purchasingGroupInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:purchasingGroupInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:purchasingGroupInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:purchasingGroupInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:purchasingGroupInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${purchasingGroupInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,66 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit PurchasingGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${purchasingGroupInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${purchasingGroupInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${purchasingGroupInstance?.id}" />
+                <input type="hidden" name="version" value="${purchasingGroupInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:purchasingGroupInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:purchasingGroupInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:purchasingGroupInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:purchasingGroupInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:purchasingGroupInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${purchasingGroupInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/list.gsp	(revision 753)
@@ -0,0 +1,69 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>PurchasingGroup List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${purchasingGroupInstanceList}" status="i" var="purchasingGroupInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/purchasingGroupDetailed/show/${purchasingGroupInstance.id}"'>
+                                ${fieldValue(bean:purchasingGroupInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/purchasingGroupDetailed/show/${purchasingGroupInstance.id}"'>
+                                ${fieldValue(bean:purchasingGroupInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/purchasingGroupDetailed/show/${purchasingGroupInstance.id}"'>
+                                ${fieldValue(bean:purchasingGroupInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/purchasingGroupDetailed/show/${purchasingGroupInstance.id}"'>
+                                ${fieldValue(bean:purchasingGroupInstance, field:'isActive')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${purchasingGroupInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${purchasingGroupInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/purchasingGroupDetailed/show.gsp	(revision 753)
@@ -0,0 +1,89 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show PurchasingGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:purchasingGroupInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:purchasingGroupInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:purchasingGroupInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:purchasingGroupInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Cost Codes:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="i" in="${purchasingGroupInstance.costCodes}">
+                                    <li><g:link controller="costCodeDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                                <g:link controller="costCodeDetailed" params="['purchasingGroup.id':purchasingGroupInstance?.id]" action="create">+Add Cost Code</g:link>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Persons:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="i" in="${purchasingGroupInstance.persons}">
+                                    <li><g:link controller="person" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                                <g:link controller="person" action="list">+Add Person</g:link>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${purchasingGroupInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/report/equipmentRegisterOhs.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/report/equipmentRegisterOhs.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/report/equipmentRegisterOhs.gsp	(revision 753)
@@ -0,0 +1,64 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Equipment Register (OH&amp;S) Report</title>
+        <nav:resources override="true"/>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <h1>Equipment Register (OH&amp;S) Report</h1>
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                        <g:jasperForm controller="report"
+                                                    action="equipmentRegisterOhs"
+                                                    jasper="equipmentRegisterOhs"
+                                                    name="Equipment Register (OH&amp;S)">
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Date:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <richui:dateChooser name="startDate" id="equipmentRegisterOhs_startDate" format="dd-MM-yyyy" value="${new Date()-7}" />
+                                    to
+                                    <richui:dateChooser name="endDate" id="equipmentRegisterOhs_endDate" format="dd-MM-yyyy" value="${new Date()}" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Section:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:select optionKey="id"
+                                                        from="${Section.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="section.id">
+                                    </g:select>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Report:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:jasperButtons jasper="equipmentRegisterOhs" format="PDF, XLS" text="PDF" />
+                                </td>
+                            </tr>
+
+                        </g:jasperForm>
+
+                    </tbody>
+                </table>
+            </div> <!--End dialog-->
+        </div> <!--End body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/report/inventoryValueDetailed.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/report/inventoryValueDetailed.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/report/inventoryValueDetailed.gsp	(revision 753)
@@ -0,0 +1,82 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Inventory Detailed Value Report</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <h1>Inventory Detailed Value Report</h1>
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                        <g:jasperForm controller="report"
+                                                    action="inventoryValueDetailed"
+                                                    jasper="inventoryValueDetailed"
+                                                    name="Inventory Value Detailed">
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Site:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:select optionKey="id"
+                                                        from="${Site.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="site.id">
+                                    </g:select>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Inventory Types:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:checkBoxList name="inventoryTypes"
+                                                                            from="${InventoryType.findAllByIsActive(true)}"
+                                                                            optionKey="id"
+                                                                            sortBy="name"
+                                                                            linkController="inventoryTypeDetailed"
+                                                                            linkAction="show"
+                                                                            height="150px"/>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Inventory Groups:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:checkBoxList name="inventoryGroups"
+                                                                            from="${InventoryGroup.findAllByIsActive(true)}"
+                                                                            optionKey="id"
+                                                                            sortBy="name"
+                                                                            linkController="inventoryGroupDetailed"
+                                                                            linkAction="show"
+                                                                            height="150px"/>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Report:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:jasperButtons jasper="inventoryValueDetailed" format="PDF, XLS" text="PDF" />
+                                </td>
+                            </tr>
+
+                        </g:jasperForm>
+
+                    </tbody>
+                </table>
+            </div> <!--End dialog-->
+        </div> <!--End body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/report/inventoryValueOverview.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/report/inventoryValueOverview.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/report/inventoryValueOverview.gsp	(revision 753)
@@ -0,0 +1,82 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Inventory Overview Value Report</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <h1>Inventory Overview Value Report</h1>
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                        <g:jasperForm controller="report"
+                                                    action="inventoryValueOverview"
+                                                    jasper="inventoryValueOverview"
+                                                    name="Inventory Value Overview">
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Site:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:select optionKey="id"
+                                                        from="${Site.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="site.id">
+                                    </g:select>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Inventory Types:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:checkBoxList name="inventoryTypes"
+                                                                            from="${InventoryType.findAllByIsActive(true)}"
+                                                                            optionKey="id"
+                                                                            sortBy="name"
+                                                                            linkController="inventoryTypeDetailed"
+                                                                            linkAction="show"
+                                                                            height="150px"/>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Inventory Groups:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:checkBoxList name="inventoryGroups"
+                                                                            from="${InventoryGroup.findAllByIsActive(true)}"
+                                                                            optionKey="id"
+                                                                            sortBy="name"
+                                                                            linkController="inventoryGroupDetailed"
+                                                                            linkAction="show"
+                                                                            height="150px"/>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Report:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:jasperButtons jasper="inventoryValueOverview" format="PDF, XLS" text="PDF" />
+                                </td>
+                            </tr>
+
+                        </g:jasperForm>
+
+                    </tbody>
+                </table>
+            </div> <!--End dialog-->
+        </div> <!--End body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/report/mandatoryRequirements.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/report/mandatoryRequirements.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/report/mandatoryRequirements.gsp	(revision 753)
@@ -0,0 +1,64 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Mandatory Requirements Report</title>
+        <nav:resources override="true"/>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <h1>Mandatory Requirements Report</h1>
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                        <g:jasperForm controller="report"
+                                                    action="mandatoryRequirements"
+                                                    jasper="mandatoryRequirements"
+                                                    name="Mandatory Requirements">
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Date:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <richui:dateChooser name="startDate" id="startDate" format="dd-MM-yyyy" value="${new Date()-7}" />
+                                    to
+                                    <richui:dateChooser name="endDate" id="endDate" format="dd-MM-yyyy" value="${new Date()}" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Section:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:select optionKey="id"
+                                                        from="${Section.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="section.id">
+                                    </g:select>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Report:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:jasperButtons jasper="mandatoryRequirements" format="PDF, XLS" text="PDF" />
+                                </td>
+                            </tr>
+
+                        </g:jasperForm>
+
+                    </tbody>
+                </table>
+            </div> <!--End dialog-->
+        </div> <!--End body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/report/regulatoryRequirements.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/report/regulatoryRequirements.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/report/regulatoryRequirements.gsp	(revision 753)
@@ -0,0 +1,64 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Regulatory Requirements Report</title>
+        <nav:resources override="true"/>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <h1>Regulatory Requirements Report</h1>
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                        <g:jasperForm controller="report"
+                                                    action="regulatoryRequirements"
+                                                    jasper="regulatoryRequirements"
+                                                    name="Regulatory Requirements">
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Date:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <richui:dateChooser name="startDate" id="startDate" format="dd-MM-yyyy" value="${new Date()-7}" />
+                                    to
+                                    <richui:dateChooser name="endDate" id="endDate" format="dd-MM-yyyy" value="${new Date()}" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Section:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <g:select optionKey="id"
+                                                        from="${Section.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="section.id">
+                                    </g:select>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Report:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:jasperButtons jasper="regulatoryRequirements" format="PDF, XLS" text="PDF" />
+                                </td>
+                            </tr>
+
+                        </g:jasperForm>
+
+                    </tbody>
+                </table>
+            </div> <!--End dialog-->
+        </div> <!--End body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/sectionDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/sectionDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/sectionDetailed/create.gsp	(revision 753)
@@ -0,0 +1,95 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Section</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${sectionInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${sectionInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:sectionInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:sectionInstance,field:'description')}"/>
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:sectionInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${sectionInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="department">Department:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'department','errors')}">
+                                    <g:select optionKey="id" from="${Department.list()}" name="department.id" value="${sectionInstance?.department?.id}" ></g:select>
+                                    <p>
+                                        <g:link controller="departmentDetailed" action="create">+Add Department</g:link>
+                                    </p>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="site">Site:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'site','errors')}">
+                                    <g:select optionKey="id" from="${Site.list()}" name="site.id" value="${sectionInstance?.site?.id}" ></g:select>
+                                    <p>
+                                        <g:link controller="siteDetailed" action="create">+Add Site</g:link>
+                                    </p>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/sectionDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/sectionDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/sectionDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,144 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit Section</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${sectionInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${sectionInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${sectionInstance?.id}" />
+                <input type="hidden" name="version" value="${sectionInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:sectionInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:sectionInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                            
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:sectionInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${sectionInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="assets">Assets:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'assets','errors')}">
+                                    
+<ul>
+<g:each var="a" in="${sectionInstance?.assets?}">
+    <li><g:link controller="assetDetailed" action="show" id="${a.id}">${a?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="assetDetailed" params="['section.id':sectionInstance?.id]" action="create">+Add Asset</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="department">Department:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'department','errors')}">
+                                    <g:select optionKey="id" from="${Department.list()}" name="department.id" value="${sectionInstance?.department?.id}" ></g:select>
+                                    <p>
+                                        <g:link controller="departmentDetailed" action="create">+Add Department</g:link>
+                                    </p>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="maintenanceActions">Maintenance Actions:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'maintenanceActions','errors')}">
+                                    
+<ul>
+<g:each var="m" in="${sectionInstance?.maintenanceActions?}">
+    <li><g:link controller="maintenanceActionDetailed" action="show" id="${m.id}">${m?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="maintenanceActionDetailed" params="['section.id':sectionInstance?.id]" action="create">+Add Maintenance Action</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="sectionExtendedAttributes">Section Extended Attributes:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'sectionExtendedAttributes','errors')}">
+                                    
+<ul>
+<g:each var="s" in="${sectionInstance?.sectionExtendedAttributes?}">
+    <li><g:link controller="sectionExtendedAttributeDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="sectionExtendedAttributeDetailed" params="['section.id':sectionInstance?.id]" action="create">+Add Extended Attribute</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="site">Site:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionInstance,field:'site','errors')}">
+                                    <g:select optionKey="id" from="${Site.list()}" name="site.id" value="${sectionInstance?.site?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/sectionDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/sectionDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/sectionDetailed/list.gsp	(revision 753)
@@ -0,0 +1,81 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Section List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                   	        <th>Department</th>
+                   	    
+                   	        <th>Site</th>
+
+                            <th></th>
+                   	    
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${sectionInstanceList}" status="i" var="sectionInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/sectionDetailed/show/${sectionInstance.id}"'>
+                                ${fieldValue(bean:sectionInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/sectionDetailed/show/${sectionInstance.id}"'>
+                                ${fieldValue(bean:sectionInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/sectionDetailed/show/${sectionInstance.id}"'>
+                                ${fieldValue(bean:sectionInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/sectionDetailed/show/${sectionInstance.id}"'>
+                                ${fieldValue(bean:sectionInstance, field:'isActive')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/sectionDetailed/show/${sectionInstance.id}"'>
+                                ${fieldValue(bean:sectionInstance, field:'department')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/sectionDetailed/show/${sectionInstance.id}"'>
+                                ${fieldValue(bean:sectionInstance, field:'site')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${sectionInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${sectionInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/sectionDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/sectionDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/sectionDetailed/show.gsp	(revision 753)
@@ -0,0 +1,121 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show Section</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:sectionInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:sectionInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:sectionInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Comment:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:sectionInstance, field:'comment')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:sectionInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Assets:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="a" in="${sectionInstance.assets}">
+                                    <li><g:link controller="assetDetailed" action="show" id="${a.id}">${a?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Department:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="departmentDetailed" action="show" id="${sectionInstance?.department?.id}">${sectionInstance?.department?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Maintenance Actions:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="m" in="${sectionInstance.maintenanceActions}">
+                                    <li><g:link controller="maintenanceActionDetailed" action="show" id="${m.id}">${m?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Section Extended Attributes:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="s" in="${sectionInstance.sectionExtendedAttributes}">
+                                    <li><g:link controller="sectionExtendedAttributeDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Site:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="siteDetailed" action="show" id="${sectionInstance?.site?.id}">${sectionInstance?.site?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${sectionInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/sectionExtendedAttributeDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/sectionExtendedAttributeDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/sectionExtendedAttributeDetailed/create.gsp	(revision 753)
@@ -0,0 +1,70 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create SectionExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Section Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${sectionExtendedAttributeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${sectionExtendedAttributeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="value">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionExtendedAttributeInstance,field:'value','errors')}">
+                                    <input type="text" maxlength="100" id="value" name="value" value="${fieldValue(bean:sectionExtendedAttributeInstance,field:'value')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionExtendedAttributeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${sectionExtendedAttributeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="extendedAttributeType">Extended Attribute Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionExtendedAttributeInstance,field:'extendedAttributeType','errors')}">
+                                    <g:select optionKey="id" from="${ExtendedAttributeType.list()}" name="extendedAttributeType.id" value="${sectionExtendedAttributeInstance?.extendedAttributeType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="section">Section:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionExtendedAttributeInstance,field:'section','errors')}">
+                                    <g:select optionKey="id" from="${Section.list()}" name="section.id" value="${sectionExtendedAttributeInstance?.section?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/sectionExtendedAttributeDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/sectionExtendedAttributeDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/sectionExtendedAttributeDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,74 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit SectionExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Section Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${sectionExtendedAttributeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${sectionExtendedAttributeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${sectionExtendedAttributeInstance?.id}" />
+                <input type="hidden" name="version" value="${sectionExtendedAttributeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="value">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionExtendedAttributeInstance,field:'value','errors')}">
+                                    <input type="text" maxlength="100" id="value" name="value" value="${fieldValue(bean:sectionExtendedAttributeInstance,field:'value')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionExtendedAttributeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${sectionExtendedAttributeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="extendedAttributeType">Extended Attribute Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionExtendedAttributeInstance,field:'extendedAttributeType','errors')}">
+                                    <g:select optionKey="id" from="${ExtendedAttributeType.list()}" name="extendedAttributeType.id" value="${sectionExtendedAttributeInstance?.extendedAttributeType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="section">Section:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:sectionExtendedAttributeInstance,field:'section','errors')}">
+                                    <g:select optionKey="id" from="${Section.list()}" name="section.id" value="${sectionExtendedAttributeInstance?.section?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/sectionExtendedAttributeDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/sectionExtendedAttributeDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/sectionExtendedAttributeDetailed/show.gsp	(revision 753)
@@ -0,0 +1,67 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show SectionExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Section Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:sectionExtendedAttributeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Value:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:sectionExtendedAttributeInstance, field:'value')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:sectionExtendedAttributeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Extended Attribute Type:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="extendedAttributeTypeDetailed" action="show" id="${sectionExtendedAttributeInstance?.extendedAttributeType?.id}">${sectionExtendedAttributeInstance?.extendedAttributeType?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Section:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="sectionDetailed" action="show" id="${sectionExtendedAttributeInstance?.section?.id}">${sectionExtendedAttributeInstance?.section?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${sectionExtendedAttributeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/shared/_assetTree.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/shared/_assetTree.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/shared/_assetTree.gsp	(revision 753)
@@ -0,0 +1,58 @@
+
+<div class="static_tree" >
+    ${assetInstance.encodeAsHTML()}
+    <g:link controller="assetSubItemDetailed" params="['asset.id':assetInstance?.id]" action="create">
+        <img src="${resource(dir:'images/skin',file:'database_add.png')}" alt="Add" title="Add Sub Item"/>
+    </g:link>
+    <g:link params="['assetToCopy.id':assetInstance?.id]" action="copy">
+        <img src="${resource(dir:'images/skin',file:'page_copy.png')}" alt="Copy" title="Copy Asset"/>
+    </g:link>
+
+    <ul>
+    <g:each var="assetSubItem1" in="${assetInstance.assetSubItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
+        <li>
+            <a href='' class="toggle"
+                                onclick="showElement('treelevel1');
+                                                return false">
+            </a>
+            <g:link controller="assetSubItemDetailed" action="show" id="${assetSubItem1.id}">${assetSubItem1?.encodeAsHTML()}</g:link>
+            <g:link controller="assetSubItemDetailed" params="['parentItem.id':assetSubItem1?.id]" action="create">
+                <img src="${resource(dir:'images/skin',file:'database_add.png')}" alt="Add" title="Add Sub Item" />
+            </g:link>
+        </li>
+
+        <div id="treelevel1">
+
+            <ul>
+            <g:each var="assetSubItem2" in="${assetSubItem1.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
+                <li>
+                    <a href='' class="toggle">
+                    </a>
+                    <g:link controller="assetSubItemDetailed" action="show" id="${assetSubItem2.id}">${assetSubItem2?.encodeAsHTML()}</g:link>
+                    <g:link controller="assetSubItemDetailed" params="['parentItem.id':assetSubItem2?.id]" action="create">
+                        <img src="${resource(dir:'images/skin',file:'database_add.png')}" alt="Add" title="Add Sub Item" />
+                    </g:link>
+                </li>
+                <ul>
+                <g:each var="assetSubItem3" in="${assetSubItem2.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
+                    <li>
+                        <g:link controller="assetSubItemDetailed" action="show" id="${assetSubItem3.id}">${assetSubItem3?.encodeAsHTML()}</g:link>
+                        <g:link controller="assetSubItemDetailed" params="['parentItem.id':assetSubItem3?.id]" action="create">
+                            <img src="${resource(dir:'images/skin',file:'database_add.png')}" alt="Add" title="Add Sub Item" />
+                        </g:link>
+                    </li>
+                    <ul>
+                    <g:each var="assetSubItem4" in="${assetSubItem3.subItems.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) } }">
+                        <li><g:link controller="assetSubItemDetailed" action="show" id="${assetSubItem4.id}">${assetSubItem4?.encodeAsHTML()}</g:link></li>
+                    </g:each> <!--assetSubItem4-->
+                    </ul>
+                </g:each> <!--assetSubItem3-->
+                </ul>
+            </g:each> <!--assetSubItem2-->
+            </ul>
+
+        </div>
+
+    </g:each> <!--assetSubItem1-->
+    </ul>
+</div>
Index: branches/features/taskProcedureRework/grails-app/views/shared/_messages.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/shared/_messages.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/shared/_messages.gsp	(revision 753)
@@ -0,0 +1,12 @@
+<g:if test="${flash.message}">
+    <div class="message">${flash.message}</div>
+</g:if>
+<g:if test="${flash.errorMessage}">
+    <div class="message_error">${flash.errorMessage}</div>
+</g:if>
+<g:if test="${params.message}">
+    <div class="message">${params.message}</div>
+</g:if>
+<g:if test="${params.errorMessage}">
+    <div class="message_error">${params.errorMessage}</div>
+</g:if>
Index: branches/features/taskProcedureRework/grails-app/views/shared/_pictureHead.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/shared/_pictureHead.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/shared/_pictureHead.gsp	(revision 753)
@@ -0,0 +1,4 @@
+
+<link rel="stylesheet" href="${resource(dir:'css',file:'lightbox.css')}" />
+<g:javascript library="lightbox" />
+<script type="text/javascript"> document.observe("dom:loaded", Lightbox.onload); </script>
Index: branches/features/taskProcedureRework/grails-app/views/siteDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/siteDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/siteDetailed/create.gsp	(revision 753)
@@ -0,0 +1,71 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Site</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${siteInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${siteInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:siteInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:siteInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:siteInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${siteInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/siteDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/siteDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/siteDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,155 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit Site</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${siteInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${siteInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${siteInstance?.id}" />
+                <input type="hidden" name="version" value="${siteInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'name','errors')}">
+                                    <input type="text" class="description" maxlength="50" id="name" name="name" value="${fieldValue(bean:siteInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'description','errors')}">
+                                    <input type="text" class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:siteInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="comment">${fieldValue(bean:siteInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${siteInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="inventoryStores">Inventory Stores:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'inventoryStores','errors')}">
+                                    
+<ul>
+<g:each var="i" in="${siteInstance?.inventoryStores?}">
+    <li><g:link controller="inventoryStoreDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="inventoryStoreDetailed" params="['site.id':siteInstance?.id]" action="create">+Add Inventory Store</g:link>
+
+                                </td>
+                            </tr> 
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="addresses">Contact:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <ul>
+                                    <g:each var="i" in="${siteInstance?.contacts}">
+                                        <li><g:link controller="contactDetailed" action="show" id="${i.id}">
+                                            ${i?.encodeAsHTML()}
+                                        </g:link></li>
+                                    </g:each>
+                                    </ul>
+                                    <g:link controller="contactDetailed" params="['site.id':siteInstance?.id]" action="create">+Add Contact</g:link>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="addresses">Addresses:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'addresses','errors')}">
+                                    
+<ul>
+<g:each var="i" in="${siteInstance?.addresses?}">
+    <li><g:link controller="addressDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="addressDetailed" params="['site.id':siteInstance?.id]" action="create">+Add Address</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="sections">Sections:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'sections','errors')}">
+                                    
+<ul>
+<g:each var="s" in="${siteInstance?.sections?}">
+    <li><g:link controller="sectionDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="sectionDetailed" params="['site.id':siteInstance?.id]" action="create">+Add Section</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="siteExtendedAttributes">Site Extended Attributes:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteInstance,field:'siteExtendedAttributes','errors')}">
+                                    
+<ul>
+<g:each var="s" in="${siteInstance?.siteExtendedAttributes?}">
+    <li><g:link controller="siteExtendedAttributeDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="siteExtendedAttributeDetailed" params="['site.id':siteInstance?.id]" action="create">+Add Extended Attribute</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/siteDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/siteDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/siteDetailed/list.gsp	(revision 753)
@@ -0,0 +1,69 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Site List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${siteInstanceList}" status="i" var="siteInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/siteDetailed/show/${siteInstance.id}"'>
+                                ${fieldValue(bean:siteInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/siteDetailed/show/${siteInstance.id}"'>
+                                ${fieldValue(bean:siteInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/siteDetailed/show/${siteInstance.id}"'>
+                                ${fieldValue(bean:siteInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/siteDetailed/show/${siteInstance.id}"'>
+                                ${fieldValue(bean:siteInstance, field:'isActive')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${siteInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${siteInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/siteDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/siteDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/siteDetailed/show.gsp	(revision 753)
@@ -0,0 +1,133 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show Site</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:siteInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:siteInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:siteInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Comment:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:siteInstance, field:'comment')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:siteInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Inventory Stores:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="i" in="${siteInstance.inventoryStores}">
+                                    <li><g:link controller="inventoryStoreDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Contact:</td>
+
+                            <td  valign="top" class="value">
+                                <ul>
+                                <g:each var="i" in="${siteInstance.contacts}">
+                                    <li><g:link controller="contactDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Addresses:</td>
+                            
+                            <td  valign="top" class="value">
+                                <ul>
+                                <g:each var="i" in="${siteInstance.addresses}">
+                                    <li><g:link controller="addressDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Sections:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="s" in="${siteInstance.sections}">
+                                    <li><g:link controller="sectionDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Site Extended Attributes:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="s" in="${siteInstance.siteExtendedAttributes}">
+                                    <li><g:link controller="siteExtendedAttributeDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${siteInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/siteExtendedAttributeDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/siteExtendedAttributeDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/siteExtendedAttributeDetailed/create.gsp	(revision 753)
@@ -0,0 +1,70 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create SiteExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Site Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${siteExtendedAttributeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${siteExtendedAttributeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="value">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteExtendedAttributeInstance,field:'value','errors')}">
+                                    <input type="text" maxlength="100" id="value" name="value" value="${fieldValue(bean:siteExtendedAttributeInstance,field:'value')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteExtendedAttributeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${siteExtendedAttributeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="extendedAttributeType">Extended Attribute Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteExtendedAttributeInstance,field:'extendedAttributeType','errors')}">
+                                    <g:select optionKey="id" from="${ExtendedAttributeType.list()}" name="extendedAttributeType.id" value="${siteExtendedAttributeInstance?.extendedAttributeType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="site">Site:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteExtendedAttributeInstance,field:'site','errors')}">
+                                    <g:select optionKey="id" from="${Site.list()}" name="site.id" value="${siteExtendedAttributeInstance?.site?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/siteExtendedAttributeDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/siteExtendedAttributeDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/siteExtendedAttributeDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,74 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit SiteExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Site Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${siteExtendedAttributeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${siteExtendedAttributeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${siteExtendedAttributeInstance?.id}" />
+                <input type="hidden" name="version" value="${siteExtendedAttributeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="value">Value:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteExtendedAttributeInstance,field:'value','errors')}">
+                                    <input type="text" maxlength="100" id="value" name="value" value="${fieldValue(bean:siteExtendedAttributeInstance,field:'value')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteExtendedAttributeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${siteExtendedAttributeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="extendedAttributeType">Extended Attribute Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteExtendedAttributeInstance,field:'extendedAttributeType','errors')}">
+                                    <g:select optionKey="id" from="${ExtendedAttributeType.list()}" name="extendedAttributeType.id" value="${siteExtendedAttributeInstance?.extendedAttributeType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="site">Site:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:siteExtendedAttributeInstance,field:'site','errors')}">
+                                    <g:select optionKey="id" from="${Site.list()}" name="site.id" value="${siteExtendedAttributeInstance?.site?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/siteExtendedAttributeDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/siteExtendedAttributeDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/siteExtendedAttributeDetailed/show.gsp	(revision 753)
@@ -0,0 +1,67 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show SiteExtendedAttribute</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Site Extended Attribute</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:siteExtendedAttributeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Value:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:siteExtendedAttributeInstance, field:'value')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:siteExtendedAttributeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Extended Attribute Type:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="extendedAttributeTypeDetailed" action="show" id="${siteExtendedAttributeInstance?.extendedAttributeType?.id}">${siteExtendedAttributeInstance?.extendedAttributeType?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Site:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="siteDetailed" action="show" id="${siteExtendedAttributeInstance?.site?.id}">${siteExtendedAttributeInstance?.site?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${siteExtendedAttributeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/supplierDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/supplierDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/supplierDetailed/create.gsp	(revision 753)
@@ -0,0 +1,73 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Supplier</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${supplierInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${supplierInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierInstance,field:'name','errors')}">
+                                    <input type="text" id="name" name="name" value="${fieldValue(bean:supplierInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:supplierInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${supplierInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="supplierType">Supplier Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierInstance,field:'supplierType','errors')}">
+                                    <g:select optionKey="id" from="${SupplierType.list()}" name="supplierType.id" value="${supplierInstance?.supplierType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/supplierDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/supplierDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/supplierDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,109 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit Supplier</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${supplierInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${supplierInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${supplierInstance?.id}" />
+                <input type="hidden" name="version" value="${supplierInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierInstance,field:'name','errors')}">
+                                    <input type="text" id="name" name="name" value="${fieldValue(bean:supplierInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:supplierInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${supplierInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="supplierType">Supplier Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierInstance,field:'supplierType','errors')}">
+                                    <g:select optionKey="id" from="${SupplierType.list()}" name="supplierType.id" value="${supplierInstance?.supplierType?.id}" ></g:select>
+                                </td>
+                            </tr> 
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="addresses">Contact:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <ul>
+                                    <g:each var="i" in="${supplierInstance?.contacts}">
+                                        <li><g:link controller="contactDetailed" action="show" id="${i.id}">
+                                            ${i?.encodeAsHTML()}
+                                        </g:link></li>
+                                    </g:each>
+                                    </ul>
+                                    <g:link controller="contactDetailed" params="['supplier.id':supplierInstance?.id]" action="create">+Add Contact</g:link>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="addresses">Addresses:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <ul>
+                                    <g:each var="i" in="${supplierInstance?.addresses?}">
+                                        <li><g:link controller="supplierDetailed" action="show" id="${i.id}">
+                                            ${i?.encodeAsHTML()}
+                                        </g:link></li>
+                                    </g:each>
+                                    </ul>
+                                    <g:link controller="addressDetailed" params="['supplier.id':supplierInstance?.id]" action="create">+Add Address</g:link>
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/supplierDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/supplierDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/supplierDetailed/list.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Supplier List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                            <g:sortableColumn property="id" title="Id" />
+
+                            <g:sortableColumn property="name" title="Name" />
+
+                            <g:sortableColumn property="description" title="Description" />
+
+                            <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th>Supplier Type</th>
+                            
+                            <th></th>
+                   	    
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${supplierInstanceList}" status="i" var="supplierInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/supplierDetailed/show/${supplierInstance.id}"'>
+                                ${fieldValue(bean:supplierInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/supplierDetailed/show/${supplierInstance.id}"'>
+                                ${fieldValue(bean:supplierInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/supplierDetailed/show/${supplierInstance.id}"'>
+                                ${fieldValue(bean:supplierInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/supplierDetailed/show/${supplierInstance.id}"'>
+                                ${fieldValue(bean:supplierInstance, field:'isActive')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/supplierDetailed/show/${supplierInstance.id}"'>
+                                ${fieldValue(bean:supplierInstance, field:'supplierType')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${supplierInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${supplierInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/supplierDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/supplierDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/supplierDetailed/show.gsp	(revision 753)
@@ -0,0 +1,96 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show Supplier</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:supplierInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:supplierInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:supplierInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:supplierInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Supplier Type:</td>
+                            
+                            <td valign="top" class="value"><g:link controller="supplierTypeDetailed" action="show" id="${supplierInstance?.supplierType?.id}">${supplierInstance?.supplierType?.encodeAsHTML()}</g:link></td>
+                            
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Contact:</td>
+
+                            <td  valign="top" class="value">
+                                <ul>
+                                <g:each var="i" in="${supplierInstance.contacts}">
+                                    <li><g:link controller="contactDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Addresses:</td>
+                            
+                            <td  valign="top" class="value">
+                                <ul>
+                                <g:each var="i" in="${supplierInstance.addresses}">
+                                    <li><g:link controller="addressDetailed" action="show" id="${i.id}">${i?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${supplierInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create SupplierType</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${supplierTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${supplierTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierTypeInstance,field:'name','errors')}">
+                                    <input type="text" id="name" name="name" value="${fieldValue(bean:supplierTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierTypeInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:supplierTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${supplierTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit SupplierType</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${supplierTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${supplierTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${supplierTypeInstance?.id}" />
+                <input type="hidden" name="version" value="${supplierTypeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierTypeInstance,field:'name','errors')}">
+                                    <input type="text" id="name" name="name" value="${fieldValue(bean:supplierTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierTypeInstance,field:'description','errors')}">
+                                    <input type="text" id="description" name="description" value="${fieldValue(bean:supplierTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${supplierTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="suppliers">Suppliers:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:supplierTypeInstance,field:'suppliers','errors')}">
+                                    
+<ul>
+<g:each var="s" in="${supplierTypeInstance?.suppliers?}">
+    <li><g:link controller="supplierDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="supplierDetailed" params="['supplierType.id':supplierTypeInstance?.id]" action="create">+Add Supplier</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/list.gsp	(revision 753)
@@ -0,0 +1,71 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>SupplierType List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                            <g:sortableColumn property="id" title="Id" />
+
+                            <g:sortableColumn property="name" title="Name" />
+
+                            <g:sortableColumn property="description" title="Description" />
+
+                            <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${supplierTypeInstanceList}" status="i" var="supplierTypeInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                            <td onclick='window.location = "${request.getContextPath()}/supplierTypeDetailed/show/${supplierTypeInstance.id}"'>
+                                ${fieldValue(bean:supplierTypeInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/supplierTypeDetailed/show/${supplierTypeInstance.id}"'>
+                                ${fieldValue(bean:supplierTypeInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/supplierTypeDetailed/show/${supplierTypeInstance.id}"'>
+                                ${fieldValue(bean:supplierTypeInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/supplierTypeDetailed/show/${supplierTypeInstance.id}"'>
+                                ${fieldValue(bean:supplierTypeInstance, field:'isActive')}
+                            </td>
+                            
+                            <td class="notClickable">
+                                <g:link action="show" id="${supplierTypeInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${supplierTypeInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/supplierTypeDetailed/show.gsp	(revision 753)
@@ -0,0 +1,76 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show SupplierType</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:supplierTypeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:supplierTypeInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:supplierTypeInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:supplierTypeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Suppliers:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="s" in="${supplierTypeInstance.suppliers}">
+                                    <li><g:link controller="supplierDetailed" action="show" id="${s.id}">${s?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${supplierTypeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create TaskBudgetStatus</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskBudgetStatus List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create TaskBudgetStatus</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskBudgetStatusInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskBudgetStatusInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskBudgetStatusInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskBudgetStatusInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskBudgetStatusInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskBudgetStatusInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskBudgetStatusInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskBudgetStatusInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit TaskBudgetStatus</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskBudgetStatus List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskBudgetStatus</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit TaskBudgetStatus</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskBudgetStatusInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskBudgetStatusInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${taskBudgetStatusInstance?.id}" />
+                <input type="hidden" name="version" value="${taskBudgetStatusInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskBudgetStatusInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskBudgetStatusInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskBudgetStatusInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskBudgetStatusInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskBudgetStatusInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskBudgetStatusInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="tasks">Tasks:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskBudgetStatusInstance,field:'tasks','errors')}">
+                                    
+<ul>
+<g:each var="t" in="${taskBudgetStatusInstance?.tasks?}">
+    <li><g:link controller="task" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="task" params="['taskBudgetStatus.id':taskBudgetStatusInstance?.id]" action="create">Add Task</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/list.gsp	(revision 753)
@@ -0,0 +1,55 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>TaskBudgetStatus List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New TaskBudgetStatus</g:link></span>
+        </div>
+        <div class="body">
+            <h1>TaskBudgetStatus List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${taskBudgetStatusInstanceList}" status="i" var="taskBudgetStatusInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${taskBudgetStatusInstance.id}">${fieldValue(bean:taskBudgetStatusInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:taskBudgetStatusInstance, field:'name')}</td>
+                        
+                            <td>${fieldValue(bean:taskBudgetStatusInstance, field:'description')}</td>
+                        
+                            <td>${fieldValue(bean:taskBudgetStatusInstance, field:'isActive')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${taskBudgetStatusInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskBudgetStatus/show.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show TaskBudgetStatus</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskBudgetStatus List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskBudgetStatus</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show TaskBudgetStatus</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskBudgetStatusInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskBudgetStatusInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskBudgetStatusInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskBudgetStatusInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Tasks:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="t" in="${taskBudgetStatusInstance.tasks}">
+                                    <li><g:link controller="task" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${taskBudgetStatusInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/_quickSearchPane.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/_quickSearchPane.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/_quickSearchPane.gsp	(revision 753)
@@ -0,0 +1,121 @@
+<!-- Start Search Pane -->
+<div class="overlayPane" id="searchPane" style="display:none;">
+    <h2>Quick Search</h2>
+
+    <g:form method="post" controller="taskDetailed">
+        <table>
+            <tbody>
+
+                <tr class="prop">
+                    <td valign="top" class="name">Select:</td>
+                    <td valign="top" class="value">
+                        <g:select optionKey="key"
+                                            optionValue="value"
+                                            from="${quickSearchSelection}"
+                                            name="quickSearch"
+                                            id="quickSearchSelect"
+                                            value="${params.quickSearch}">
+                        </g:select>
+
+                            <span id="allTasksHelp">
+                                <g:helpBalloon class="helpballoon" code="task.search.text.all.tasks" />
+                            </span>
+                            <span id="personsTasksHelp">
+                                <g:helpBalloon class="helpballoon" code="task.search.text.persons.tasks" />
+                            </span>
+                            <span id="personsImmediateCalloutsHelp">
+                                <g:helpBalloon class="helpballoon" code="task.search.text.persons.immediate.callouts" />
+                            </span>
+                    </td>
+                </tr>
+
+                <tr class="prop">
+                    <td valign="top" class="name">
+                        <label for="date">Between:</label>
+                    </td>
+                    <td valign="top" class="value">
+                        <richui:dateChooser name="startDate" format="dd-MM-yyyy" value="${params.startDate}" />
+                        and
+                        <richui:dateChooser name="endDate" format="dd-MM-yyyy" value="${params.endDate}" />
+                    </td>
+                </tr>
+
+                <tr class="prop" style="height:2.7em;">
+                    <td valign="top" class="name">
+                        <label for="person.id" id="personLabel">Person:</label>
+                    </td>
+                    <td valign="top" class="value">
+                        <div id="personSelection">
+                            <g:select optionKey="id"
+                                                from="${Person.findAllByIsActive(true).sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }}"
+                                                name="person.id"
+                                                value="${params.person?.id}"
+                                                id="personSelector">
+                            </g:select>
+                        </div>
+                    </td>
+                </tr>
+
+                <tr class="prop" style="height:2.7em;">
+                    <td valign="top" class="name">
+                        <label for="includeCompleted" id="completedLabel">Incl. Completed:</label>
+                    </td>
+                    <td valign="top" class="value">
+                        <div id="completedSelection">
+                            <g:checkBox name="includeCompleted"
+                                                    value="${params.includeCompleted}"
+                                                    id="completedSelector">
+                            </g:checkBox>
+                            <g:helpBalloon class="helpballoon" code="task.search.include.completed" />
+                        </div>
+                    </td>
+                </tr>
+
+            </tbody>
+        </table>
+
+        <div class="buttons">
+            <span class="button">
+                <g:actionSubmit class="save" value="Update" action="${actionName}" />
+                <g:actionSubmit class="cancel" value="${g.message(code:'fp.tag.filterPane.button.cancel.text', default:'Cancel')}" onclick="return hideElement('searchPane');" />
+            </span>
+        </div>
+    </g:form>
+
+    <table>
+        <tbody>
+            <tr class="prop">
+                <td valign="top" class="name">
+                    <label>My Tasks:</label>
+                </td>
+                <td valign="top" class="value">
+                    <g:link controller="taskDetailed"
+                                    action="${actionName}"
+                                    params="[quickSearch: 'myTodays']">
+                                    <g:message code="task.search.text.my.todays" />
+                    </g:link> - <g:message code="task.search.text.my.todays.description" />
+                    <br />
+                </td>
+            </tr>
+
+            <tr class="prop">
+                <td valign="top" class="name">
+                    <label>Links:</label>
+                </td>
+                <td valign="top" class="value">
+                    <g:link controller="taskDetailed"
+                                    action="workDone">
+                                    <g:message code="task.search.text.work.done" />
+                    </g:link> - <g:message code="task.search.text.work.done.description" />
+                    <br />
+                    <g:link controller="taskDetailed"
+                                    action="workLoad">
+                                    <g:message code="task.search.text.work.load" />
+                    </g:link> - <g:message code="task.search.text.work.load.description" />
+                </td>
+            </tr>
+
+        </tbody>
+    </table>
+
+</div> <!-- end search pane -->
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/create.gsp	(revision 753)
@@ -0,0 +1,200 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Task</title>
+        <nav:resources override="true"/>
+        <resource:dateChooser />
+    </head>
+    <body onload="document.createTaskForm.description.focus();">
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${taskInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+
+            <g:form action="save" method="post" name="createTaskForm">
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'description','errors')}">
+                                    <input type="text"  class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:taskInstance,field:'description')}"/>
+                                    <g:helpBalloon class="helpballoon" code="task.description" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'comment','errors')}">
+                                    <textarea  rows="5" cols="40" name="comment">${fieldValue(bean:taskInstance, field:'comment')}</textarea>
+                                    <g:helpBalloon class="helpballoon" code="task.comment" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="targetStartDate">Target Start Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'targetStartDate','errors')}">
+                                    <richui:dateChooser name="targetStartDate" format="dd-MM-yyyy" value="${taskInstance.targetStartDate}" />
+                                    <g:helpBalloon class="helpballoon" code="task.targetStartDate" />
+                                </td>
+                            </tr> 
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="targetCompletionDate">Target Completion Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'targetCompletionDate','errors')}">
+                                    <richui:dateChooser name="targetCompletionDate" format="dd-MM-yyyy" value="${taskInstance.targetCompletionDate}" />
+                                    <g:helpBalloon class="helpballoon" code="task.targetCompletionDate" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="leadPerson">Lead Person:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'leadPerson','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${Person.findAllByIsActive(true).sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }}"
+                                                        name="leadPerson.id"
+                                                        value="${taskInstance?.leadPerson?.id}" >
+                                    </g:select>
+                                    <g:helpBalloon code="task.leadPerson" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="primaryAsset">Primary Asset:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'primaryAsset','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${Asset.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="primaryAsset.id"
+                                                        value="${taskInstance?.primaryAsset?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.none.select.text')}/]">
+                                    </g:select>
+                                    <g:helpBalloon code="task.primaryAsset" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="associatedAssets">Associated Assets:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'associatedAssets','errors')}">
+                                    <g:select id="associatedAssets" name="associatedAssets"
+                                                    from="${Asset.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                    size="5" multiple="yes" optionKey="id"
+                                                    value="${taskInstance?.associatedAssets?.id}"
+                                                    noSelection="['':/${g.message(code:'default.none.select.text')}/]">
+                                    </g:select>
+                                    <g:helpBalloon code="task.associatedAssets" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskPriority">Task Priority:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'taskPriority','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${scheduledTaskPriorities}"
+                                                        name="taskPriority.id"
+                                                        value="${taskInstance?.taskPriority?.id}" >
+                                    </g:select>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskGroup">Task Group:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'taskGroup','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${TaskGroup.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="taskGroup.id"
+                                                        value="${taskInstance?.taskGroup?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.please.select.text')}/]">
+                                    </g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskType">Task Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'taskType','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${scheduledTaskTypes}"
+                                                        name="taskType.id"
+                                                        value="${taskInstance?.taskType?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.please.select.text')}/]">
+                                    </g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="safetyRequirement">Safety:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'safetyRequirement','errors')}">
+                                    <g:checkBox name="safetyRequirement" value="${taskInstance?.safetyRequirement}" ></g:checkBox>
+                                    <g:helpBalloon code="task.safetyRequirement" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="regulatoryRequirement">Regulatory:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'regulatoryRequirement','errors')}">
+                                    <g:checkBox name="regulatoryRequirement" value="${taskInstance?.regulatoryRequirement}" ></g:checkBox>
+                                    <g:helpBalloon code="task.regulatoryRequirement" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="mandatoryRequirement">Mandatory:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'mandatoryRequirement','errors')}">
+                                    <g:checkBox name="mandatoryRequirement" value="${taskInstance?.mandatoryRequirement}" ></g:checkBox>
+                                    <g:helpBalloon code="task.mandatoryRequirement" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="positiveFault">Positive Fault:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'positiveFault','errors')}">
+                                    <g:checkBox name="positiveFault" value="${taskInstance?.positiveFault}" ></g:checkBox>
+                                    <g:helpBalloon code="task.positiveFault" />
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/createImmediateCallout.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/createImmediateCallout.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/createImmediateCallout.gsp	(revision 753)
@@ -0,0 +1,162 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Immediate Callout</title>
+        <nav:resources override="true"/>
+        <resource:dateChooser />
+    </head>
+    <body onload="document.createTaskForm.description.focus();">
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+
+            <g:hasErrors>
+                <div class="errors">
+                    <ul>
+                        <g:eachError bean="${taskInstance}">
+                            <li><g:message error="${it}" /></li>
+                        </g:eachError>
+                        <g:eachError bean="${entryFaultInstance}">
+                            <li><g:message error="${it}" /></li>
+                        </g:eachError>
+                        <g:eachError bean="${entryCauseInstance}">
+                            <li><g:message error="${it}" /></li>
+                        </g:eachError>
+                        <g:eachError bean="${entryWorkDoneInstance}">
+                            <li><g:message error="${it}" /></li>
+                        </g:eachError>
+                    </ul>
+                </div>
+            </g:hasErrors>
+
+            <g:form action="saveImmediateCallout" method="post" name="createTaskForm">
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Callout Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'description','errors')}">
+                                    <input type="text"  class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:taskInstance,field:'description')}"/>
+                                    <g:helpBalloon class="helpballoon" code="task.description.immediateCallout" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="targetStartDate">Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'targetStartDate','errors')}">
+                                    <richui:dateChooser name="targetStartDate" format="dd-MM-yyyy" value="${taskInstance.targetStartDate}" />
+                                    <g:helpBalloon class="helpballoon" code="task.targetStartDate.immediateCallout" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="primaryAsset">Asset:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'primaryAsset','errors')}">
+                                    <g:select optionKey="id"
+                                                    from="${Asset.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                    name="primaryAsset.id" value="${taskInstance?.primaryAsset?.id}"
+                                                    noSelection="['null':/${g.message(code:'default.none.select.text')}/]">
+                                    </g:select>
+                                    <g:helpBalloon code="task.primaryAsset" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="productionReference">Production:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryFaultInstance,field:'productionReference','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${ProductionReference.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="entryFault.productionReference.id"
+                                                        value="${entryFaultInstance?.productionReference?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.none.select.text')}/]">
+                                    </g:select>
+                                    <g:helpBalloon code="entry.productionReference.fault" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="durationHour">Down Time:</label>
+                                </td>
+
+                                <td valign="top" class="value">
+                                    <input class="time ${hasErrors(bean:entryFaultInstance,field:'durationHour','errors')}"
+                                        type="text" id="entryFault.durationHour" name="entryFault.durationHour"
+                                        value="${fieldValue(bean:entryFaultInstance,field:'durationHour')}" />
+                                    :
+                                    <input class="time ${hasErrors(bean:entryFaultInstance,field:'durationMinute','errors')}"
+                                        type="text" id="entryFault.durationMinute" name="entryFault.durationMinute" 
+                                        value="${fieldValue(bean:entryFaultInstance,field:'durationMinute')}" />
+                                    <g:helpBalloon code="entry.duration.fault" />
+                                </td> 
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">${entryFaultInstance?.entryType.encodeAsHTML()}:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryFaultInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="entryFault.comment">${fieldValue(bean:entryFaultInstance, field:'comment')}</textarea>
+                                        <g:helpBalloon code="entry.comment.fault" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">${entryCauseInstance?.entryType.encodeAsHTML()}:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryCauseInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="entryCause.comment">${fieldValue(bean:entryCauseInstance, field:'comment')}</textarea>
+                                        <g:helpBalloon code="entry.comment.cause" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">${entryWorkDoneInstance?.entryType.encodeAsHTML()}:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:entryWorkDoneInstance,field:'comment','errors')}">
+                                    <textarea rows="5" cols="40" name="entryWorkDone.comment">${fieldValue(bean:entryWorkDoneInstance, field:'comment')}</textarea>
+                                        <g:helpBalloon code="entry.comment.work.done" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="durationHour">Work Duration:</label>
+                                </td>
+
+                                <td valign="top" class="value">
+                                    <input class="time ${hasErrors(bean:entryWorkDoneInstance,field:'durationHour','errors')}"
+                                        type="text" id="entryWorkDone.durationHour" name="entryWorkDone.durationHour"
+                                        value="${fieldValue(bean:entryWorkDoneInstance,field:'durationHour')}" />
+                                    :
+                                    <input class="time ${hasErrors(bean:entryWorkDoneInstance,field:'durationMinute','errors')}"
+                                        type="text" id="entryWorkDone.durationMinute" name="entryWorkDone.durationMinute" 
+                                        value="${fieldValue(bean:entryWorkDoneInstance,field:'durationMinute')}" />
+                                    <g:helpBalloon code="entry.duration" />
+                                </td> 
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/createUnscheduled.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/createUnscheduled.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/createUnscheduled.gsp	(revision 753)
@@ -0,0 +1,172 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create Task</title>
+        <nav:resources override="true"/>
+        <resource:dateChooser />
+    </head>
+    <body onload="document.createTaskForm.description.focus();">
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+
+            <g:form action="saveUnscheduled" method="post" name="createTaskForm">
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'description','errors')}">
+                                    <input type="text"  class="description" maxlength="75" id="description" name="description" value="${fieldValue(bean:taskInstance,field:'description')}"/>
+                                    <g:helpBalloon class="helpballoon" code="task.description" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'comment','errors')}">
+                                    <textarea  rows="5" cols="40" name="comment">${fieldValue(bean:taskInstance, field:'comment')}</textarea>
+                                    <g:helpBalloon class="helpballoon" code="task.comment" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="targetStartDate">Target Start Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'targetStartDate','errors')}">
+                                    <richui:dateChooser name="targetStartDate" format="dd-MM-yyyy" value="${taskInstance.targetStartDate}" />
+                                    <g:helpBalloon class="helpballoon" code="task.targetStartDate" />
+                                </td>
+                            </tr> 
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="targetCompletionDate">Target Completion Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'targetCompletionDate','errors')}">
+                                    <richui:dateChooser name="targetCompletionDate" format="dd-MM-yyyy" value="${taskInstance.targetCompletionDate}" />
+                                    <g:helpBalloon class="helpballoon" code="task.targetCompletionDate" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="leadPerson">Lead Person:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'leadPerson','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${Person.findAllByIsActive(true).sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }}"
+                                                        name="leadPerson.id"
+                                                        value="${taskInstance?.leadPerson?.id}" >
+                                    </g:select>
+                                    <g:helpBalloon code="task.leadPerson" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="primaryAsset">Asset:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'primaryAsset','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${Asset.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="primaryAsset.id"
+                                                        value="${taskInstance?.primaryAsset?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.none.select.text')}/]">
+                                        </g:select>
+                                    <g:helpBalloon code="task.primaryAsset" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskPriority">Task Priority:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'taskPriority','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${unscheduledTaskPriorities}"
+                                                        name="taskPriority.id"
+                                                        value="${taskInstance?.taskPriority?.id}" >
+                                    </g:select>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskGroup">Task Group:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'taskGroup','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${TaskGroup.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="taskGroup.id"
+                                                        value="${taskInstance?.taskGroup?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.please.select.text')}/]">
+                                    </g:select>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskType">Task Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'taskType','errors')}">
+                                    ${taskInstance.taskType.encodeAsHTML()}
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="safetyRequirement">Safety Requirement:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'safetyRequirement','errors')}">
+                                    <g:checkBox name="safetyRequirement" value="${taskInstance?.safetyRequirement}" ></g:checkBox>
+                                    <g:helpBalloon code="task.safetyRequirement" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="regulatoryRequirement">Regulatory Requirement:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'regulatoryRequirement','errors')}">
+                                    <g:checkBox name="regulatoryRequirement" value="${taskInstance?.regulatoryRequirement}" ></g:checkBox>
+                                    <g:helpBalloon code="task.regulatoryRequirement" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="mandatoryRequirement">Mandatory Requirement:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'mandatoryRequirement','errors')}">
+                                    <g:checkBox name="mandatoryRequirement" value="${taskInstance?.mandatoryRequirement}" ></g:checkBox>
+                                    <g:helpBalloon code="task.mandatoryRequirement" />
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,251 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit Task #${taskInstance?.id}</title>
+        <nav:resources override="true"/>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${taskInstance?.id}" />
+                <input type="hidden" name="version" value="${taskInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="id">Id:</label>
+                                </td>
+                                <td valign="top" class="value">${fieldValue(bean:taskInstance, field:'id')}</td>
+                            </tr>
+
+                            <g:if test="${taskInstance?.parentTask}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">Parent Task:</td>
+
+                                    <td valign="top" class="value"><g:link controller="taskDetailed" action="show" id="${taskInstance.parentTask.id}">${taskInstance.parentTask.encodeAsHTML()}</g:link></td>
+
+                                </tr>
+                            </g:if>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'description','errors')}">
+                                    <input type="text" style="width:450px" maxlength="75" id="description" name="description" value="${fieldValue(bean:taskInstance,field:'description')}"/>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="comment">Comment:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'comment','errors')}">
+                                    <textarea style="width:450px" rows="5" cols="40" name="comment">${fieldValue(bean:taskInstance, field:'comment')}</textarea>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="targetStartDate">Target Start Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'targetStartDate','errors')}">
+                                    <richui:dateChooser name="targetStartDate" format="dd-MM-yyyy" value="${taskInstance?.targetStartDate}" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="targetCompletionDate">Target Completion Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'targetCompletionDate','errors')}">
+                                    <richui:dateChooser name="targetCompletionDate" format="dd-MM-yyyy" value="${taskInstance?.targetCompletionDate}" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="leadPerson">Lead Person:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'leadPerson','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${Person.findAllByIsActive(true).sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }}"
+                                                        name="leadPerson.id"
+                                                        value="${taskInstance?.leadPerson?.id}" >
+                                    </g:select>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="primaryAsset">Primary Asset:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'primaryAsset','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${Asset.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="primaryAsset.id"
+                                                        value="${taskInstance?.primaryAsset?.id}"
+                                                        noSelection="['null':/${g.message(code:'default.none.select.text')}/]">
+                                    </g:select>
+                                    <g:helpBalloon code="task.primaryAsset" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="associatedAssets">Associated Assets:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'associatedAssets','errors')}">
+                                    <g:select id="associatedAssets"
+                                                    name="associatedAssets"
+                                                    from="${Asset.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                    optionKey="id" size="5" multiple="yes" 
+                                                    value="${taskInstance?.associatedAssets.id}"
+                                                    noSelection="['':/${g.message(code:'default.none.select.text')}/]">
+                                    </g:select>
+                                    <g:helpBalloon  class="helpballoon" code="task.associatedAssets" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskPriority">Task Priority:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'taskPriority','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${TaskPriority.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="taskPriority.id"
+                                                        value="${taskInstance?.taskPriority?.id}" >
+                                    </g:select>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskGroup">Task Group:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'taskGroup','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${TaskGroup.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="taskGroup.id"
+                                                        value="${taskInstance?.taskGroup?.id}" >
+                                    </g:select>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskType">Task Type:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'taskType','errors')}">
+                                    <g:select optionKey="id"
+                                                        from="${TaskType.findAllByIsActive(true).sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }}"
+                                                        name="taskType.id"
+                                                        value="${taskInstance?.taskType?.id}" >
+                                    </g:select>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="safetyRequirement">Safety Requirement:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'safetyRequirement','errors')}">
+                                    <g:checkBox name="safetyRequirement" value="${taskInstance?.safetyRequirement}" ></g:checkBox>
+                                    <g:helpBalloon code="task.safetyRequirement" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="regulatoryRequirement">Regulatory Requirement:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'regulatoryRequirement','errors')}">
+                                    <g:checkBox name="regulatoryRequirement" value="${taskInstance?.regulatoryRequirement}" ></g:checkBox>
+                                    <g:helpBalloon code="task.regulatoryRequirement" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="mandatoryRequirement">Mandatory Requirement:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'mandatoryRequirement','errors')}">
+                                    <g:checkBox name="mandatoryRequirement" value="${taskInstance?.mandatoryRequirement}" ></g:checkBox>
+                                    <g:helpBalloon code="task.mandatoryRequirement" />
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="positiveFault">Positive Fault:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'positiveFault','errors')}">
+                                    <g:checkBox name="positiveFault" value="${taskInstance?.positiveFault}" ></g:checkBox>
+                                    <g:helpBalloon code="task.positiveFault" />
+                                </td>
+                            </tr> 
+
+                            <g:if test="${taskInstance.assignedGroups}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="assignedPersons">Assigned Groups:</label>
+                                    </td>
+                                    <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'assignedGroups','errors')}">
+                                        
+                                    <ul>
+                                    <g:each var="a" in="${taskInstance?.assignedGroups?}">
+                                        <li><g:link controller="assignedGroupDetailed" action="edit" id="${a.id}" params="['task.id':taskInstance?.id]">${a?.encodeAsHTML()}</g:link></li>
+                                    </g:each>
+                                    </ul>
+
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                            <g:if test="${taskInstance.assignedPersons}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="assignedPersons">Assigned Persons:</label>
+                                    </td>
+                                    <td valign="top" class="value ${hasErrors(bean:taskInstance,field:'assignedPersons','errors')}">
+                                        
+                                    <ul>
+                                    <g:each var="a" in="${taskInstance?.assignedPersons?}">
+                                        <li><g:link controller="assignedPersonDetailed" action="edit" id="${a.id}" params="['task.id':taskInstance?.id]">${a?.encodeAsHTML()}</g:link></li>
+                                    </g:each>
+                                    </ul>
+
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="trash" onclick="return confirm('Are you sure?');" value="Trash" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/listSubTasks.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/listSubTasks.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/listSubTasks.gsp	(revision 753)
@@ -0,0 +1,85 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Task List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+
+            <h1>Sub Tasks for:
+                <g:link action="show" id="${parentTaskInstance.id}" params="[showTab:'showSubTasksTab']">
+                    Task #${parentTaskInstance.id}
+                </g:link>
+            </h1>
+            ${parentTaskInstance.description}
+
+            <g:if test="${flash.message}">
+                <div class="message">${flash.message}</div>
+            </g:if>
+
+            <div class="paginateButtons">
+                Results: ${taskInstanceList.size()} / ${taskInstanceTotal}
+            </div>
+            <div class="paginateButtons">
+                <g:paginate action="listSubTasks" id="${parentTaskInstance?.id}" total="${taskInstanceTotal}" />
+            </div>
+            <div class="list">
+                <input type="hidden" name="parentTaskId" value="${parentTaskInstance?.id}" />
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn action="listSubTasks" property="id" title="Id" />
+                        
+                   	        <g:sortableColumn action="listSubTasks"  property="targetStartDate" title="Target Start Date" />
+                        
+                            <g:sortableColumn action="listSubTasks"  property="description" title="Description" />
+                        
+                   	        <g:sortableColumn action="listSubTasks"  property="leadPerson" title="Lead Person" />
+                        
+                            <g:sortableColumn action="listSubTasks"  property="taskPriority" title="Task Priority" />
+                        
+                            <g:sortableColumn action="listSubTasks"  property="taskStatus" title="Task Status" />
+
+                            <th></th>
+                   	    
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${taskInstanceList}" status="i" var="taskInstance">
+                    <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}" onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'/>
+
+                            <td>${fieldValue(bean:taskInstance, field:'id')}</td>
+                        
+                            <td><g:formatDate date="${taskInstance.targetStartDate}" format="EEE, dd-MMM-yyyy"/></td>
+                        
+                            <td>${fieldValue(bean:taskInstance, field:'description')}</td>
+                        
+                            <td>${fieldValue(bean:taskInstance, field:'leadPerson')}</td>
+                        
+                            <td>${fieldValue(bean:taskInstance, field:'taskPriority')}</td>
+                        
+                            <td>${fieldValue(bean:taskInstance, field:'taskStatus')}</td>
+
+                            <td>
+                                <g:link action="show" id="${taskInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate action="listSubTasks" id="${parentTaskInstance?.id}" total="${taskInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/search.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/search.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/search.gsp	(revision 753)
@@ -0,0 +1,255 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Task Search</title>
+        <filterpane:includes />
+        <nav:resources override="true"/>
+        <export:resource />
+        <resource:dateChooser />
+        <g:javascript src="taskQuickSearchPane.js" />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${appCore}">
+                <div class="errors">
+                    <g:renderErrors bean="${appCore}" as="list" />
+                </div>
+            </g:hasErrors>
+            <filterpane:currentCriteria domainBean="Task"
+                                    action="search"
+                                    dateFormat="EEE, dd-MMM-yyyy"
+                                    removeImgDir="images"
+                                    removeImgFile="bullet_delete.png"
+                                    title="Advanced Search"/>
+
+            <div class="paginateButtons">
+                <span class="searchButtons">
+                    <a href='' onclick="showElement('searchPane'); return false;">Quick</a>
+                </span>
+                Results: ${taskInstanceList.size()} / ${taskInstanceTotal}
+                <span class="searchButtons">
+                    <filterpane:filterButton text="Advanced" appliedText="Advanced" />
+                </span>
+            </div>
+
+            <jsUtil:toggleControl toggleId="options"
+                                                    imageId="optionsImg"
+                                                    closedImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_right.png')}"
+                                                    openImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_down.png')}"
+                                                    text="${g.message(code: 'default.options.text')}"
+                                                    />
+
+            <div id="options" style="display:none;">
+                <g:form method="post" action="setSearchParamsMax" >
+                    <g:hiddenField name="params" value="${filterParams}" />
+                    <div class="dialog">
+                        <table>
+                            <tbody>
+
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="max">Results per page:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <input type="text" maxlength="4" id="description" name="newMax" value="${params.max}"/>
+
+                                        <span class="buttons">
+                                            <g:actionSubmit action="setSearchParamsMax" class="go" value="Update" />
+                                        </span>
+                                    </td>
+                                </tr>
+
+                            </tbody>
+                        </table>
+                    </div>
+                <export:formats  params="${filterParams}" formats="['csv', 'excel', 'pdf', 'rtf']"/>
+                </g:form>
+            </div>
+
+            <br />
+
+            <g:if test="${taskInstanceTotal > taskInstanceList.size()}">
+                <div class="paginateButtons">
+                    <g:paginate action="search" total="${taskInstanceTotal}" params="${filterParams}" />
+                </div>
+            </g:if>
+
+            <g:if test="${taskInstanceList.size() > 0}">
+                <div class="list">
+                    <table>
+                        <thead>
+                            <tr>
+
+                                <custom:sortableColumnWithImg property="attentionFlag"
+                                                                                                imgSrc="${resource(dir:'images/skin',file:'flag_red.png')}"
+                                                                                                imgAlt="Flag"
+                                                                                                imgTitle="Attention Flag"
+                                                                                                params="${filterParams}" />
+
+                                <g:sortableColumn property="targetStartDate" title="Target Start Date" params="${filterParams}" />
+
+                                <g:sortableColumn property="description" title="Description" params="${filterParams}" />
+
+                                <g:sortableColumn property="taskGroup" title="Group" params="${filterParams}" />
+
+                                <g:sortableColumn  property="taskType" title="Type" params="${filterParams}" />
+
+                                <custom:sortableColumnWithImg property="taskStatus"
+                                                                                                imgSrc="${resource(dir:'images/skin',file:'status.png')}"
+                                                                                                imgAlt="Status"
+                                                                                                imgTitle="Status"
+                                                                                                params="${filterParams}" />
+
+                                <g:sortableColumn  property="taskPriority" title="Priority" params="${filterParams}" />
+
+                                <custom:sortableColumnWithImg property="defaultSort"
+                                                                                                imgSrc="${resource(dir:'images/skin',file:'table_sort.png')}"
+                                                                                                imgAlt="Sort"
+                                                                                                imgTitle="Default Sort"
+                                                                                                params="${filterParams}" />
+
+                            </tr>
+                        </thead>
+                        </tbody>
+                        <tbody>
+                        <g:each in="${taskInstanceList}" status="i" var="taskInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                <td class="idColumn" onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    <g:if test="${taskInstance.attentionFlag}">
+                                        <img  src="${resource(dir:'images/skin',file:'flag_red.png')}" alt="Flag" title="Attention Flag"/>
+                                    </g:if>
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    <g:formatDate date="${taskInstance.targetStartDate}" format="EEE, dd-MMM-yyyy"/>
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    <b>
+                                        Task #${fieldValue(bean:taskInstance, field:'id')}
+                                    </b>
+                                    <g:if test="${taskInstance.approved}" >
+                                        <img  src="${resource(dir:'images/skin',file:'cog.png')}" alt="Approved" title="Approved" />
+                                    </g:if>
+                                    <g:if test="${taskInstance.taskRecurringSchedule?.enabled}" >
+                                        <img  src="${resource(dir:'images/skin',file:'arrow_refresh.png')}" alt="Recurrence Enabled" title="Recurrence Enabled" />
+                                    </g:if>
+                                    <br />
+
+                                    <b>
+                                    ${fieldValue(bean:taskInstance, field:'description')}
+                                    </b>
+                                    <g:if test="${taskInstance.safetyRequirement}" >
+                                        <br />
+                                        <img  src="${resource(dir:'images/skin',file:'lightning.png')}" alt="Safety Requirement" title="Safety Requirement" />
+                                        Safety
+                                    </g:if>
+                                    <g:if test="${taskInstance.regulatoryRequirement}" >
+                                        <br />
+                                        <img  src="${resource(dir:'images/skin',file:'script_lightning.png')}" alt="Regulatory Requirement" title="Regulatory Requirement" />
+                                        Regulatory
+                                    </g:if>
+                                    <g:if test="${taskInstance.mandatoryRequirement}" >
+                                        <br />
+                                        <img  src="${resource(dir:'images/skin',file:'script.png')}" alt="Mandatory Requirement" title="Mandatory Requirement" />
+                                        Mandatory
+                                    </g:if>
+                                    <br />
+                                    <br />
+                                    <g:if test="${taskInstance.primaryAsset}">
+                                        ${fieldValue(bean:taskInstance, field:'primaryAsset')}<br />
+                                    </g:if>
+                                    <g:each in="${taskInstance.assignedGroups}" status="j" var="assignedGroup">
+                                        ${assignedGroup.encodeAsHTML()}<br />
+                                    </g:each>
+                                    <g:each in="${taskInstance.assignedPersons}" status="k" var="assignedPerson">
+                                        ${assignedPerson.encodeAsHTML()}<br />
+                                    </g:each>
+                                    <g:each in="${taskInstance.entries}" status="m" var="entry">
+                                        <g:if test="${entry.entryType.id == 3}">
+                                            <em>${'WD: ' +entry.toShortString().encodeAsHTML()}</em><br />
+                                        </g:if>
+                                    </g:each>
+                                    <g:if test="${taskInstance.subTasks}">
+                                        Sub Tasks: ${taskInstance.subTasks.size()}<br />
+                                    </g:if>
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    ${fieldValue(bean:taskInstance, field:'taskGroup')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    ${fieldValue(bean:taskInstance, field:'taskType')}
+                                </td>
+
+                                <td class="idColumn" onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    <g:if test="${taskInstance.taskStatus.id == 1}" >
+                                        <img  src="${resource(dir:'images/skin',file:'not_started.png')}" alt="Not Started" title="Not Started" />
+                                    </g:if>
+                                    <g:if test="${taskInstance.taskStatus.id == 2}" >
+                                        <img  src="${resource(dir:'images/skin',file:'arrow_right.png')}" alt="In Progress" title="In Progress" />
+                                    </g:if>
+                                    <g:if test="${taskInstance.taskStatus.id == 3}" >
+                                        <img  src="${resource(dir:'images/skin',file:'tick.png')}" alt="Complete" title="Complete" />
+                                    </g:if>
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    ${fieldValue(bean:taskInstance, field:'taskPriority')}
+                                </td>
+
+                                <td class="notClickable">
+                                    <g:link action="show" id="${taskInstance.id}">
+                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" title="Show" />
+                                    </g:link>
+                                </td>
+
+                            </tr>
+                        </g:each>
+                        </tbody>
+                    </table>
+                </div>
+            </g:if>
+            <div class="paginateButtons">
+                <g:paginate action="search" total="${taskInstanceTotal}" params="${filterParams}" />
+            </div>
+
+            <filterpane:filterPane domainBean="Task"
+                                    title="Advanced Search"
+                                    action="search"
+                                    class="overlayPane"
+                                    additionalProperties="id"
+                                    excludeProperties="targetCompletionDate"
+                                    associatedProperties="taskPriority.name,
+                                                                                leadPerson.lastName,
+                                                                                leadPerson.firstName,
+                                                                                taskGroup.name,
+                                                                                associatedAssets.name,
+                                                                                primaryAsset.name,
+                                                                                taskStatus.name,
+                                                                                taskType.name"
+                                    filterPropertyValues="${['taskPriority.name':[values: associatedPropertyValues.taskPriorityList],
+                                                                                'leadPerson.lastName':[values: associatedPropertyValues.lastNameList],
+                                                                                'leadPerson.firstName':[values: associatedPropertyValues.firstNameList],
+                                                                                'taskGroup.name':[values: associatedPropertyValues.taskGroupList],
+                                                                                'associatedAssets.name':[values: associatedPropertyValues.assetList],
+                                                                                'primaryAsset.name':[values: associatedPropertyValues.assetList],
+                                                                                'taskStatus.name':[values: associatedPropertyValues.taskStatusList],
+                                                                                'taskType.name':[values: associatedPropertyValues.taskTypeList],
+                                                                                targetCompletionDate:[years: associatedPropertyValues.yearRange,precision:'day'],
+                                                                                targetStartDate:[years: associatedPropertyValues.yearRange,precision:'day']
+                                                                                ]}"/>
+
+            <g:render template="quickSearchPane" />
+
+        </div> <!-- end body  -->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/searchCalendar.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/searchCalendar.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/searchCalendar.gsp	(revision 753)
@@ -0,0 +1,144 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Task Search Calendar</title>
+        <filterpane:includes />
+        <nav:resources override="true"/>
+        <resource:calendarMonthView  skin="calendarmonthviewCustom"/>
+        <export:resource />
+        <resource:dateChooser />
+        <g:javascript src="taskQuickSearchPane.js" />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+
+        <div class="body">
+            <g:render template="/shared/messages" />
+
+            <filterpane:currentCriteria domainBean="Task"
+                                    action="searchCalendar"
+                                    dateFormat="EEE, dd-MMM-yyyy"
+                                    removeImgDir="images" 
+                                    removeImgFile="bullet_delete.png"
+                                    title="Advanced Search"/>
+
+
+            <div class="paginateButtons">
+                <span class="searchButtons">
+                    <a href='' onclick="showElement('searchPane'); return false;">Quick</a>
+                </span>
+                Results: ${taskInstanceList.size()} / ${taskInstanceTotal}
+                <span class="searchButtons">
+                    <filterpane:filterButton text="Advanced" appliedText="Advanced" />
+                </span>
+            </div>
+
+            <jsUtil:toggleControl toggleId="options"
+                                                    imageId="optionsImg"
+                                                    closedImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_right.png')}"
+                                                    openImgUrl="${resource(dir:'images/skin',file:'bullet_arrow_down.png')}"
+                                                    text="${g.message(code: 'default.options.text')}"
+                                                    />
+
+            <div id="options" style="display:none;">
+                <g:form method="post" action="setSearchCalendarParamsMax" >
+                    <g:hiddenField name="params" value="${filterParams}" />
+                    <div class="dialog">
+                        <table>
+                            <tbody>
+
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="max">Results per page:</label>
+                                    </td>
+                                    <td valign="top" class="value">
+                                        <input type="text" maxlength="4" id="description" name="newMax" value="${params.max}"/>
+
+                                        <span class="buttons">
+                                            <g:actionSubmit action="setSearchCalendarParamsMax" class="go" value="Update" />
+                                        </span>
+                                    </td>
+                                </tr>
+
+                            </tbody>
+                        </table>
+                    </div>
+                <export:formats  params="${filterParams}" formats="['csv', 'excel', 'pdf', 'rtf']"/>
+                </g:form>
+            </div>
+
+            <br />
+
+            <g:if test="${taskInstanceList.size() > 0}">
+                    <div class="paginateButtons">
+                        <g:link action="searchCalendar"
+                                        params="[showMonth: previousYear.month, showYear: previousYear.year]">
+                            &lt;&lt;
+                        </g:link>
+                        <g:link action="searchCalendar"
+                                        params="[showMonth: previousMonth.month, showYear: previousMonth.year]">
+                            &lt;
+                        </g:link>
+                        <span class="calendarMonthControlTitle">
+                            <g:formatDate date="${showDate}" format="MMMM, yyyy"/>
+                        </span>
+                        <g:link action="searchCalendar"
+                                        params="[showMonth: nextMonth.month, showYear: nextMonth.year]">
+                            &gt;
+                        </g:link>
+                        <g:link action="searchCalendar"
+                                        params="[showMonth: nextYear.month, showYear: nextYear.year]">
+                            &gt;&gt;
+                        </g:link>
+                    </div>
+                    <div>
+                        <g:link action="searchCalendar"
+                                        params="[showMonth: today.month, showYear: today.year]">
+                            Today: <g:formatDate date="${today.date}" format="MMMM, yyyy"/>
+                        </g:link>
+                    </div>
+                    <br />
+
+                <richui:calendarMonthView items="${taskInstanceList}"
+                                                                        createLink="true"
+                                                                        constraintDateFields="['targetStartDate']"
+                                                                        month="${showDate}"
+                                                                        controller="taskDetailed"
+                                                                        action="show"
+                                                                        dayAction="create"/>
+            </g:if>
+
+            <filterpane:filterPane domainBean="Task"
+                                    title="Advanced Search"
+                                    action="searchCalendar"
+                                    class="overlayPane"
+                                    additionalProperties="id"
+                                    excludeProperties="trash, targetCompletionDate"
+                                    associatedProperties="taskPriority.name,
+                                                                                leadPerson.lastName,
+                                                                                leadPerson.firstName,
+                                                                                taskGroup.name,
+                                                                                associatedAssets.name,
+                                                                                primaryAsset.name,
+                                                                                taskStatus.name,
+                                                                                taskType.name"
+                                    filterPropertyValues="${['taskPriority.name':[values: associatedPropertyValues.taskPriorityList],
+                                                                                'leadPerson.lastName':[values: associatedPropertyValues.lastNameList],
+                                                                                'leadPerson.firstName':[values: associatedPropertyValues.firstNameList],
+                                                                                'taskGroup.name':[values: associatedPropertyValues.taskGroupList],
+                                                                                'associatedAssets.name':[values: associatedPropertyValues.assetList],
+                                                                                'primaryAsset.name':[values: associatedPropertyValues.assetList],
+                                                                                'taskStatus.name':[values: associatedPropertyValues.taskStatusList],
+                                                                                'taskType.name':[values: associatedPropertyValues.taskTypeList],
+                                                                                targetCompletionDate:[years: associatedPropertyValues.yearRange,precision:'day'],
+                                                                                targetStartDate:[years: associatedPropertyValues.yearRange,precision:'day']
+                                                                                ]}"/>
+
+            <g:render template="quickSearchPane" />
+
+        </div> <!-- end body div -->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/show.gsp	(revision 753)
@@ -0,0 +1,864 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show Task #${taskInstance.id}</title>
+        <nav:resources override="true"/>
+        <resource:tabView skin="tabviewCustom" />
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="nav"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:if test="${taskInstance.trash}" >
+                <div class="errors">
+                        <ul><li>This task is in the trash bin, but can be restored if required.<li><ul>
+                </div>
+            </g:if>
+            <g:hasErrors bean="${taskInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+
+            <div class="tabHeader">
+                <h1>
+                    Task #${taskInstance.id}
+
+                    <g:if test="${taskInstance.approved}" >
+                        <img  src="${resource(dir:'images/skin',file:'cog.png')}" alt="Approved" title="Approved" />
+                    </g:if>
+                    <g:if test="${taskRecurringScheduleInstance?.enabled}" >
+                        <img  src="${resource(dir:'images/skin',file:'arrow_refresh.png')}" alt="Recurrence Enabled" title="Recurrence Enabled" />
+                    </g:if>
+                    <g:if test="${taskInstance.taskStatus.id == 2}" >
+                        <img  src="${resource(dir:'images/skin',file:'arrow_right.png')}" alt="In Progress" title="In Progress" />
+                    </g:if>
+                    <g:if test="${taskInstance.attentionFlag}" >
+                        <img  src="${resource(dir:'images/skin',file:'flag_red.png')}" alt="Attention Flag" title="Attention Flag" />
+                    </g:if>
+                    <g:if test="${taskInstance.taskStatus.id == 3}" >
+                        <img  src="${resource(dir:'images/skin',file:'tick.png')}" alt="Complete" title="Complete" />
+                    </g:if>
+                </h1>
+                ${fieldValue(bean:taskInstance, field:'description')}
+                <g:if test="${taskInstance.safetyRequirement}" >
+                    <img  src="${resource(dir:'images/skin',file:'lightning.png')}" alt="Safety Requirement" title="Safety Requirement" />
+                    Safety
+                </g:if>
+                <g:if test="${taskInstance.regulatoryRequirement}" >
+                    <img  src="${resource(dir:'images/skin',file:'script_lightning.png')}" alt="Regulatory Requirement" title="Regulatory Requirement" />
+                    Regulatory
+                </g:if>
+                <g:if test="${taskInstance.mandatoryRequirement}" >
+                    <img  src="${resource(dir:'images/skin',file:'script.png')}" alt="Mandatory Requirement" title="Mandatory Requirement" />
+                    Mandatory
+                </g:if>
+            </div>
+
+            <br/>
+
+            <richui:tabView id="tabView">
+
+                <richui:tabLabels>
+                    <richui:tabLabel selected="${showTab.task}" title="Details" />
+                    <g:if test="${taskProcedureExits}">
+                        <richui:tabLabel selected="${showTab.procedure}" title="Procedure (!)" />
+                    </g:if>
+                    <g:else>
+                        <richui:tabLabel selected="${showTab.procedure}" title="Procedure" />
+                    </g:else>
+                    <g:if test="${taskRecurringScheduleExits}">
+                        <richui:tabLabel selected="${showTab.recurrence}" title="Recurrence (!)" />
+                    </g:if>
+                    <g:else>
+                        <richui:tabLabel selected="${showTab.recurrence}" title="Recurrence" />
+                    </g:else>
+                    <g:if test="${!inventoryMovementList.isEmpty()}">
+                        <richui:tabLabel selected="${showTab.inventory}" title="Inventory (${inventoryMovementList.size()})" />
+                    </g:if>
+                    <g:else>
+                        <richui:tabLabel selected="${showTab.inventory}" title="Inventory (0)" />
+                    </g:else>
+                    <g:if test="${subTaskInstanceTotal > 0}">
+                        <richui:tabLabel selected="${showTab.subTasks}" title="Sub Tasks (${subTaskInstanceTotal})" />
+                    </g:if>
+                    <g:else>
+                        <richui:tabLabel selected="${showTab.subTasks}" title="Sub Tasks (0)" />
+                    </g:else>
+                </richui:tabLabels>
+
+                <richui:tabContents>
+
+<!-- Start Task tab -->
+                    <richui:tabContent>
+
+                        <div class="dialog">
+                            <table>
+                                <tbody>
+
+                                    <g:if test="${taskInstance.parentTask}">
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Parent Task:</td>
+
+                                            <td valign="top" class="value">
+                                                <g:link controller="taskDetailed" action="show" id="${taskInstance.parentTask.id}">
+                                                    ${taskInstance.parentTask.encodeAsHTML()}
+                                                </g:link>
+                                            </td>
+
+                                        </tr>
+                                    </g:if>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Comment:</td>
+
+                                        <td valign="top" class="value">${fieldValue(bean:taskInstance, field:'comment')}</td>
+
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Target Start:</td>
+
+                                        <td valign="top" class="value">
+                                            <g:formatDate date="${taskInstance.targetStartDate}" format="EEE, dd-MMM-yyyy"/>
+                                        </td>
+
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Target Completion:</td>
+
+                                        <td valign="top" class="value">
+                                            <g:formatDate date="${taskInstance.targetCompletionDate}" format="EEE, dd-MMM-yyyy"/>
+                                        </td>
+
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">
+
+                                            <jsUtil:toggleControl toggleId="modifications"
+                                                                                    imageId="modificationsImg"
+                                                                                    closedImgUrl="${resource(dir:'images/skin',file:'bullet_toggle_plus.png')}"
+                                                                                    openImgUrl="${resource(dir:'images/skin',file:'bullet_toggle_minus.png')}"
+                                                                                    effect="fade"
+                                                                                    text="Modifications"
+                                                                                    />
+                                        </td>
+
+                                        <td  valign="top" style="text-align:left;" class="value">
+                                            <div id="modifications" style="display:none;">
+                                                <ul>
+                                                <g:each var="a" in="${taskModificationList}">
+                                                    <li>${a?.encodeAsHTML()}</li>
+                                                </g:each>
+                                                </ul>
+                                            </div>
+                                        </td>
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Primary Asset:</td>
+
+                                        <td valign="top" class="value"><g:link controller="assetDetailed" action="show" id="${taskInstance?.primaryAsset?.id}">${taskInstance?.primaryAsset?.encodeAsHTML()}</g:link></td>
+
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Associated Assets:</td>
+
+                                        <td  valign="top" style="text-align:left;" class="value">
+                                            <ul>
+                                            <g:each var="a" in="${taskInstance.associatedAssets}">
+                                                <li>${a?.encodeAsHTML()}</li>
+                                            </g:each>
+                                            </ul>
+                                        </td>
+
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Priority:</td>
+
+                                        <td valign="top" class="value">${taskInstance?.taskPriority?.encodeAsHTML()}</td>
+
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Positive Fault:</td>
+
+                                        <td valign="top" class="value">${fieldValue(bean:taskInstance, field:'positiveFault')}</td>
+
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Group:</td>
+
+                                        <td valign="top" class="value">${taskInstance?.taskGroup?.encodeAsHTML()}</td>
+
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Type:</td>
+
+                                        <td valign="top" class="value">${taskInstance?.taskType?.encodeAsHTML()}</td>
+
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Lead Person:</td>
+
+                                        <td valign="top" class="value">${taskInstance?.leadPerson?.encodeAsHTML()}</td>
+
+                                    </tr>
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Assigned Groups:</td>
+
+                                        <td  valign="top" style="text-align:left;" class="value">
+                                            <ul>
+                                            <g:each var="a" in="${assignedGroupList}">
+                                                <li><g:link controller="assignedGroupDetailed" action="edit" id="${a.id}" params="['task.id':taskInstance.id]">${a?.encodeAsHTML()}</g:link></li>
+                                            </g:each>
+                                            </ul>
+                                            <g:link controller="assignedGroupDetailed" action="create" params="['task.id':taskInstance.id]">+Add Group</g:link>
+                                        </td>
+
+                                    </tr>
+
+
+                                    <tr class="prop">
+                                        <td valign="top" class="name">Assigned Persons:</td>
+
+                                        <td  valign="top" style="text-align:left;" class="value">
+                                            <ul>
+                                            <g:each var="a" in="${assignedPersonList}">
+                                                <li><g:link controller="assignedPersonDetailed" action="edit" id="${a.id}" params="['task.id':taskInstance.id]">${a?.encodeAsHTML()}</g:link></li>
+                                            </g:each>
+                                            </ul>
+                                            <g:link controller="assignedPersonDetailed" action="create" params="['task.id':taskInstance?.id]">+Add Person</g:link>
+                                        </td>
+
+                                    </tr>
+
+                                </tbody>
+                            </table>
+                        </div>
+
+                        <div class="buttons">
+                            <g:form>
+                                <input type="hidden" name="id" value="${taskInstance?.id}" />
+
+                                <g:if test="${taskInstance.trash}" >
+                                    <span class="button"><g:actionSubmit class="restore" onclick="return confirm('Are you sure?');" value="Restore"/></span>
+                                </g:if>
+                                <g:else>
+
+                                    <g:if test="${taskInstance.taskStatus.id != 3}" >
+
+                                        <g:if test="${taskInstance.attentionFlag}" >
+                                            <span class="button"><g:actionSubmit class="flag" value="Clear" action="clearAttentionFlag"/></span>
+                                        </g:if>
+                                        <g:else>
+                                            <span class="button"><g:actionSubmit class="flag" value="Unresolved" action="setAttentionFlag"/></span>
+                                            <g:helpBalloon class="helpballoon" code="task.status.unresolved" />
+                                        </g:else>
+
+                                        <span class="button"><g:actionSubmit class="complete" value="Resolved" action="complete"/></span>
+                                        <g:helpBalloon class="helpballoon" code="task.status.resolved" />
+
+                                        <g:if test="${taskInstance.approved}" >
+                                            <span class="button"><g:actionSubmit class="renegeApproval" value="Renege Approval" action="renegeApproval" /></span>
+                                        </g:if>
+                                        <g:else>
+                                            <span class="button"><g:actionSubmit class="approve" value="Approve" /></span>
+                                        </g:else>
+
+                                        <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                                        <span class="button"><g:actionSubmit class="trash" onclick="return confirm('Are you sure?');" value="Trash" /></span>
+
+                                    </g:if>
+                                    <g:else>
+                                        <span class="button"><g:actionSubmit class="reopen" value="Reopen" /></span>
+                                    </g:else>
+
+                                </g:else>
+                            </g:form>
+                        </div>
+
+                        <br />
+
+                        <g:if test="${entryFaultList.isEmpty()}">
+                            <h1>No Faults</h1>
+                            <br />
+                        </g:if>
+                        <g:else>
+                            <div class="list">
+                                <h1>Faults</h1>
+                                <table>
+                                    <thead>
+                                        <tr>
+                                            <th>Comment</th>
+                                            <th>Date</th>
+                                            <th>Production</th>
+                                            <th>Down Time</th>
+                                            <th>Entered By</th>
+                                            <th></th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                        <g:each in="${entryFaultList}" status="i" var="entry">
+                                                <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                                    <td style="width:65%" onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.comment.encodeAsHTML()}
+                                                    </td>
+
+                                                    <td onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        <g:formatDate date="${entry.dateDone}" format="EEE, dd-MMM-yyyy"/>
+                                                    </td>
+
+                                                    <td onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        <g:if test="${entry.productionReference}">
+                                                            ${entry.productionReference.encodeAsHTML()}
+                                                        </g:if>
+                                                        <g:else>
+                                                            <g:message code="default.none.text" />
+                                                        </g:else>
+                                                    </td>
+
+                                                    <td onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.durationHour}:${entry.durationMinute}
+                                                    </td>
+
+                                                    <td onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.enteredBy.encodeAsHTML()}
+                                                    </td>
+
+                                                    <td class="notClickable">
+                                                        <g:link controller="entryDetailed" action="edit" id="${entry.id}">
+                                                            <img  src="${resource(dir:'images/skin',file:'database_edit.png')}" alt="Edit" title="Edit" />
+                                                        </g:link>
+                                                    </td>
+
+                                                </tr>
+                                        </g:each>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </g:else>
+
+                        <div class="buttons">
+                            <g:form controller="entryDetailed">
+                                <g:hiddenField name="taskInstance.id" value="${taskInstance?.id}" />
+                                <g:hiddenField name="entryType.id" value="1" />
+                                <span class="button">
+                                    <g:actionSubmit value="Add Fault" action="create"  class="add"/>
+                                </span>
+                            </g:form>
+                        </div>
+
+                        <br />
+
+                        <g:if test="${entryCauseList.isEmpty()}">
+                            <h1>No Causes</h1>
+                            <br />
+                        </g:if>
+                        <g:else>
+                            <div class="list">
+                                <h1>Causes</h1>
+                                <table>
+                                    <thead>
+                                        <tr>
+                                            <th>Comment</th>
+                                            <th>Date Done</th>
+                                            <th>Entered By</th>
+                                            <th></th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                        <g:each in="${entryCauseList}" status="i" var="entry">
+                                                <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                                    <td style="width:65%" onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.comment.encodeAsHTML()}
+                                                    </td>
+
+                                                    <td onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        <g:formatDate date="${entry.dateDone}" format="EEE, dd-MMM-yyyy"/>
+                                                    </td>
+
+                                                    <td onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.enteredBy.encodeAsHTML()}
+                                                    </td>
+
+                                                    <td class="notClickable">
+                                                        <g:link controller="entryDetailed" action="edit" id="${entry.id}">
+                                                            <img  src="${resource(dir:'images/skin',file:'database_edit.png')}" alt="Edit" title="Edit" />
+                                                        </g:link>
+                                                    </td>
+
+                                                </tr>
+                                        </g:each>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </g:else>
+
+                        <div class="buttons">
+                            <g:form controller="entryDetailed">
+                                <g:hiddenField name="taskInstance.id" value="${taskInstance?.id}" />
+                                <g:hiddenField name="entryType.id" value="2" />
+                                <span class="button">
+                                    <g:actionSubmit value="Add Cause" action="create"  class="add"/>
+                                </span>
+                            </g:form>
+                        </div>
+
+                        <br />
+
+                        <g:if test="${entryWorkDoneList.isEmpty()}">
+                            <h1>No Work Done</h1>
+                            <br />
+                        </g:if>
+                        <g:else>
+                            <div class="list">
+                                <h1>Work Done</h1>
+                                <table>
+                                    <thead>
+                                        <tr>
+                                            <th>Comment</th>
+                                            <th>Date Done</th>
+                                            <th>Duration</th>
+                                            <th>Entered By</th>
+                                            <th></th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                        <g:each in="${entryWorkDoneList}" status="i" var="entry">
+                                                <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                                    <td width="65%" onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.comment.encodeAsHTML()}
+                                                    </td>
+                                                    
+                                                    <td onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        <g:formatDate date="${entry.dateDone}" format="EEE, dd-MMM-yyyy"/>
+                                                    </td>
+                                                    
+                                                    <td onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.durationHour}:${entry.durationMinute}
+                                                    </td>
+                                                    
+                                                    <td onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.enteredBy.encodeAsHTML()}
+                                                    </td>
+
+                                                    <td class="notClickable">
+                                                        <g:link controller="entryDetailed" action="edit" id="${entry.id}">
+                                                            <img  src="${resource(dir:'images/skin',file:'database_edit.png')}" alt="Edit" title="Edit" />
+                                                        </g:link>
+                                                    </td>
+
+                                                </tr>
+                                        </g:each>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </g:else>
+
+                        <div class="buttons">
+                            <g:form controller="entryDetailed">
+                                <g:hiddenField name="taskInstance.id" value="${taskInstance?.id}" />
+                                <g:hiddenField name="entryType.id" value="3" />
+                                <span class="button">
+                                    <g:actionSubmit value="Add Work Done" action="create"  class="add"/>
+                                </span>
+                            </g:form>
+                        </div>
+                    </richui:tabContent>
+<!-- End Task tab -->
+
+
+<!-- Start Task Procedure tab-->
+                    <richui:tabContent>
+                        <g:if test="${!taskProcedureExits}">
+                            <br />
+                            No Procedure linked.
+                            <br />
+                            <br />
+                            <g:form controller="taskProcedureDetailed" >
+                                <g:hiddenField name="taskInstance.id" value="${taskInstance?.id}" />
+
+                                <div class="buttons">
+                                    <span class="button">
+                                        <g:actionSubmit value="New" action="create" class="add"/>
+                                    </span>
+                                    <span class="button">
+                                        <g:actionSubmit value="Search" action="search" class="search"/>
+                                    </span>
+                                </div>
+
+                            </g:form>
+
+                        </g:if>
+                        <g:else>
+                            <div class="dialog">
+                                <table>
+                                    <tbody>
+
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Procedure Id:</td>
+
+                                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'id')}</td>
+
+                                        </tr>
+
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Name:</td>
+
+                                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'name')}</td>
+
+                                        </tr>
+
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Description:</td>
+
+                                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'description')}</td>
+
+                                        </tr>
+
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Is Active:</td>
+
+                                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'isActive')}</td>
+
+                                        </tr>
+
+                                    </tbody>
+                                </table>
+                            </div>
+                            <div class="buttons">
+                                <g:form controller="taskProcedureDetailed">
+                                    <input type="hidden" name="id" value="${taskProcedureInstance?.id}" />
+                                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                                </g:form>
+                            </div>
+
+                            <div class="list">
+                                <table>
+                                    <thead>
+                                        <tr>
+                                            <th>Step</th>
+                                            <th>Description</th>
+                                            <th>Reasoning</th>
+                                            <th>Asset</th>
+                                            <th>Sub Item</th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                        <g:each in="${maintenanceActionList}" status="i" var="maintenanceAction">
+                                            <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+
+                                                <td valign="top" class="name">
+                                                    ${fieldValue(bean:maintenanceAction, field:'procedureStepNumber')}
+                                                </td>
+
+                                                <td  valign="top" style="text-align:left;" class="value">
+                                                    ${fieldValue(bean:maintenanceAction, field:'description')}
+                                                </td>
+
+                                                <td  valign="top" style="text-align:left;" class="value">
+                                                    ${fieldValue(bean:maintenanceAction, field:'reasoning')}
+                                                </td>
+
+                                                <td  valign="top" style="text-align:left;" class="value">
+                                                    ${fieldValue(bean:maintenanceAction, field:'asset')}
+                                                </td>
+
+                                                <td  valign="top" style="text-align:left;" class="value">
+                                                    ${fieldValue(bean:maintenanceAction, field:'assetSubItem')}
+                                                </td>
+
+                                            </tr>
+                                        </g:each>
+
+                                    </tbody>
+                                </table>
+                            </div>
+
+                        </g:else>
+
+                    </richui:tabContent>
+<!-- End Task Procedure tab-->
+
+<!-- Start Task Recurrence tab -->
+                    <richui:tabContent>
+
+                        <g:if test="${!taskRecurringScheduleExits}">
+                            <br />
+                            No Recurring Schedule.
+                            <br />
+                            <br />
+                            <g:form controller="taskRecurringScheduleDetailed" >
+                                <g:hiddenField name="task.id" value="${taskInstance.id}" />
+
+                                <div class="buttons">
+                                    <span class="button">
+                                        <g:actionSubmit value="Add" action="create" class="add" />
+                                    </span>
+                                </div>
+
+                            </g:form>
+
+                        </g:if>
+                        <g:else>
+
+                        <div class="dialog">
+                                <table>
+                                    <tbody>
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Recurring Schedule:</td>
+
+                                            <td valign="top" class="value">${taskRecurringScheduleInstance.encodeAsHTML()}</td>
+                                        </tr>
+
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Enabled:</td>
+
+                                            <td valign="top" class="value">${fieldValue(bean:taskRecurringScheduleInstance, field:'enabled')}</td>
+                                        </tr>
+
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Next Generation Date:</td>
+
+                                            <td valign="top" class="value">
+                                                <g:formatDate date="${taskRecurringScheduleInstance.nextGenerationDate}" format="EEE, dd-MMM-yyyy"/>
+                                            </td>
+                                        </tr>
+
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Generate Ahead:</td>
+
+                                            <td valign="top" class="value">
+                                                ${taskRecurringScheduleInstance?.generateAhead} ${Period.get(1).encodeAsHTML()}
+                                            </td>
+                                        </tr>
+
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Next Target Start Date:</td>
+
+                                            <td valign="top" class="value">
+                                                <g:formatDate date="${taskRecurringScheduleInstance.nextTargetStartDate}" format="EEE, dd-MMM-yyyy"/>
+                                            </td>
+                                        </tr>
+
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Task Duration:</td>
+
+                                            <td valign="top" class="value">
+                                                ${taskRecurringScheduleInstance?.taskDuration} ${taskRecurringScheduleInstance?.taskDurationPeriod}
+                                            </td>
+                                        </tr>
+
+                                        <tr class="prop">
+                                            <td valign="top" class="name">Next Target Completion Date:</td>
+
+                                            <td valign="top" class="value">
+                                                <g:formatDate date="${taskRecurringScheduleInstance.nextTargetCompletionDate}" format="EEE, dd-MMM-yyyy"/>
+                                            </td>
+                                        </tr>
+
+                                    </tbody>
+                                </table>
+                            </div>
+                            <div class="buttons">
+                                <g:form controller="taskRecurringScheduleDetailed">
+                                    <input type="hidden" name="id" value="${taskRecurringScheduleInstance?.id}" />
+                                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                                    <span class="button"><g:actionSubmit class="go" value="Show" /></span>
+                                </g:form>
+                            </div>
+
+                        </g:else>
+                    </richui:tabContent>
+<!-- End Task Recurrence tab -->
+
+<!-- Start Inventory tab -->
+                    <richui:tabContent>
+
+                        <g:if test="${inventoryMovementList.isEmpty()}">
+                            <br />
+                            No Inventory Movements.
+                            <br />
+                            <br />
+                        </g:if>
+                        <g:else>
+                            <div class="list">
+                                <table>
+                                    <thead>
+                                        <tr>
+                                            <th>Inventory Item</th>
+                                            <th>Quantity</th>
+                                            <th>Movement Type</th>
+                                            <th>Date</th>
+                                            <th></th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                        <g:each in="${inventoryMovementList}" status="i" var="inventoryMovementInstance">
+                                            <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${inventoryMovementInstance.id}"'>
+                                                    ${fieldValue(bean:inventoryMovementInstance, field:'inventoryItem')}
+                                                </td>
+
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${inventoryMovementInstance.id}"'>
+                                                    ${fieldValue(bean:inventoryMovementInstance, field:'quantity')}
+                                                </td>
+
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${inventoryMovementInstance.id}"'>
+                                                    ${fieldValue(bean:inventoryMovementInstance, field:'inventoryMovementType')}
+                                                </td>
+
+                                                <td onclick='window.location = "${request.getContextPath()}/inventoryMovementDetailed/show/${inventoryMovementInstance.id}"'>
+                                                    <g:formatDate date="${inventoryMovementInstance.date}" format="EEE, dd-MMM-yyyy"/>
+                                                </td>
+
+                                                <td class="notClickable">
+                                                    <g:link controller="inventoryMovementDetailed" action="show" id="${inventoryMovementInstance.id}">
+                                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" title="Show" />
+                                                    </g:link>
+                                                </td>
+
+                                            </tr>
+                                        </g:each>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </g:else>
+
+                        <g:form controller="inventoryItemDetailed" >
+                            <g:hiddenField name="task.id" value="${taskInstance?.id}" />
+                            <div class="buttons">
+                                <g:if test="${!inventoryMovementList.isEmpty()}">
+                                    Results: ${inventoryMovementList.size()}
+                                    <br />
+                                </g:if>
+                                <span class="button">
+                                    <g:actionSubmit action="findInventoryItemForMovement" class="add" value="Add" />
+                                </span>
+                            </div>
+                        </g:form>
+
+                    </richui:tabContent>
+<!-- End Inventory tab -->
+
+<!-- Start Sub Task tab -->
+                    <richui:tabContent>
+                        <g:if test="${subTaskInstanceTotal > 0}">
+                            <div class="list">
+                                <table>
+                                    <thead>
+                                        <tr>
+
+                                            <th>Id</th>
+
+                                            <th>Target Start Date</th>
+
+                                            <th>Description</th>
+
+                                            <th>Lead Person</th>
+
+                                            <th>Task Priority</th>
+
+                                            <th>Task Status</th>
+
+                                            <th></th>
+
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                    <g:each in="${subTaskInstanceList}" status="i" var="subTaskInstance">
+                                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                            <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${subTaskInstance.id}"'>
+                                                ${fieldValue(bean:subTaskInstance, field:'id')}
+                                            </td>
+
+                                            <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${subTaskInstance.id}"'>
+                                                <g:formatDate date="${subTaskInstance.targetStartDate}" format="EEE, dd-MMM-yyyy"/>
+                                            </td>
+
+                                            <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${subTaskInstance.id}"'>
+                                                ${fieldValue(bean:subTaskInstance, field:'description')}
+                                            </td>
+
+
+                                            <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${subTaskInstance.id}"'>
+                                                ${fieldValue(bean:subTaskInstance, field:'leadPerson')}
+                                            </td>
+
+                                            <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${subTaskInstance.id}"'>
+                                                ${fieldValue(bean:subTaskInstance, field:'taskPriority')}
+                                            </td>
+
+                                            <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${subTaskInstance.id}"'>
+                                                ${fieldValue(bean:subTaskInstance, field:'taskStatus')}
+                                            </td>
+
+                                            <td class="notClickable">
+                                                <g:link action="show" id="${subTaskInstance.id}">
+                                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" title="Show" />
+                                                </g:link>
+                                            </td>
+
+                                        </tr>
+                                    </g:each>
+                                    </tbody>
+                                </table>
+                            </div>
+
+                            <div class="buttons">
+                                <g:form>
+                                    <g:hiddenField name="id" value="${taskInstance?.id}" />
+                                    <g:if test="${subTaskInstanceTotal > subTaskInstanceMax}">
+                                        Showing ${subTaskInstanceMax} of ${subTaskInstanceTotal}
+                                        <br />
+                                    </g:if>
+                                    <g:else>
+                                        Total ${subTaskInstanceTotal}
+                                        <br />
+                                    </g:else>
+                                    <span class="button"><g:actionSubmit action="listSubTasks" class="table" value="List" /></span>
+                                    <span class="button"><g:actionSubmit action="createSubTask" class="save" value="Create" onclick="return confirm('${g.message(code: 'sub.task.create.confirm')}');" /></span>
+                                </g:form>
+                            </div>
+
+                        </g:if>
+                        <g:else>
+                            <br />
+                            No Sub Tasks.
+                            <br />
+                            <br />
+
+                            <div class="buttons">
+                                <g:form>
+                                    <g:hiddenField name="id" value="${taskInstance?.id}" />
+                                    <span class="button"><g:actionSubmit action="createSubTask" class="save" value="Create" onclick="return confirm('${g.message(code: 'sub.task.create.confirm')}');" /></span>
+                                </g:form>
+                            </div>
+                        </g:else>
+
+                    </richui:tabContent>
+<!-- End Sub Task tab -->
+
+                </richui:tabContents>
+            </richui:tabView>
+
+        </div> <!--body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/workDone.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/workDone.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/workDone.gsp	(revision 753)
@@ -0,0 +1,114 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Work Done</title>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Work Done</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+
+            <div class="paginateButtons">
+                Results: ${totalEntries}
+                <span class="searchButtons">
+                    <a href='' onclick="showElement('searchPane'); return false;">Search</a>
+                </span>
+            </div>
+
+            <br />
+
+                <g:if test="${entries.size() > 0}">
+                            <div class="list">
+                                <table>
+                                    <thead>
+                                        <tr>
+                                            <th>Task</th>
+                                            <th>Work Done</th>
+                                            <th>Duration</th>
+                                            <th></th>
+                                        </tr>
+                                    </thead>
+                                    <tbody>
+                                        <g:each in="${entries}" status="i" var="entry">
+                                                <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                                    <td width="35%" onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.task.encodeAsHTML()}
+                                                    </td>
+                                                    <td width="60%" onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.comment.encodeAsHTML()}
+                                                    </td>
+                                                    <td onclick='window.location = "${request.getContextPath()}/entryDetailed/edit/${entry.id}"'>
+                                                        ${entry.durationHour}:<g:formatNumber number="${entry.durationMinute}" type="number" minIntegerDigits="2" />
+                                                    </td>
+
+                                                    <td class="notClickable">
+                                                        <g:link controller="entryDetailed" action="edit" id="${entry.id}">
+                                                            <img  src="${resource(dir:'images/skin',file:'database_edit.png')}" alt="Edit" />
+                                                        </g:link>
+                                                    </td>
+
+                                                </tr>
+                                        </g:each>
+                                        <tr class="total">
+                                            <td>
+                                                Total
+                                            </td>
+                                            <td>
+                                            </td>
+                                            <td>
+                                                ${totalHours}:<g:formatNumber number="${totalMinutes}" type="number" minIntegerDigits="2" />
+                                            </td>
+                                            <td>
+                                            </td>
+                                        </tr>
+                                    </tbody>
+                                </table>
+                            </div>
+                        </g:if>
+
+            <!-- Start Search Pane -->
+            <div class="overlayPane" id="searchPane" style="display:none;">
+                <h2>Search</h2>
+                <g:form method="post" controller="taskDetailed">
+                    <table>
+                        <tbody>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">Person:</td>
+                                <td valign="top" class="value">
+                                    <g:select optionKey="id"
+                                                        from="${Person.findAllByIsActive(true).sort { p1, p2 -> p1.firstName.compareToIgnoreCase(p2.firstName) }}"
+                                                        name="person.id"
+                                                        value="${person.id}" >
+                                    </g:select>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="date">Date:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <richui:dateChooser name="date" format="dd-MM-yyyy" value="${startOfDay}" />
+                                </td>
+                            </tr>
+
+                        </tbody>
+                    </table>
+                    <div class="buttons">
+                        <span class="button">
+                            <g:actionSubmit class="save" value="Update" action="workDone" />
+                            <g:actionSubmit class="cancel" value="${g.message(code:'fp.tag.filterPane.button.cancel.text', default:'Cancel')}" onclick="return hideElement('searchPane');" />
+                        </span>
+                    </div>
+                </g:form>
+            </div> <!-- end search pane -->
+
+        </div> <!--body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskDetailed/workLoad.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskDetailed/workLoad.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskDetailed/workLoad.gsp	(revision 753)
@@ -0,0 +1,226 @@
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Work Load</title>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Work Load</h1>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+
+            <div class="paginateButtons">
+                <span class="searchButtons">
+                    <a href='' onclick="showElement('searchPane'); return false;">Search</a>
+                </span>
+            </div>
+
+            <br />
+
+
+            <g:if test="${workLoadGroups.size() > 0}">
+                <h1>Assigned Groups</h1>
+            </g:if>
+            <g:else>
+                <h1>No Assigned Groups Found</h1>
+            </g:else>
+                    <div class="list">
+                        <table>
+                            <thead>
+                                <tr>
+                                    <th>Assigned Group</th>
+                                    <th>Duration</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                                <g:each in="${workLoadGroups}" status="i" var="workLoadGroup">
+                                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                            <td class="notClickable">
+                                                ${workLoadGroup.key}
+                                            </td>
+
+                                            <td class="notClickable">
+                                                ${workLoadGroup.value.hours}:<g:formatNumber number="${workLoadGroup.value.minutes}" type="number" minIntegerDigits="2" />
+                                            </td>
+
+                                        </tr>
+                                </g:each>
+                            </tbody>
+                                <tr class="total">
+                                    <td>
+                                        Total
+                                    </td>
+                                    <td>
+                                        ${totalHours}:<g:formatNumber number="${totalMinutes}" type="number" minIntegerDigits="2" />
+                                    </td>
+                                </tr>
+                        </table>
+                    </div>
+
+            <br />
+
+            <h1>Task Results: ${tasks.size()} / ${tasks.totalCount}</h1>
+
+            <g:if test="${tasks.size() > 0}">
+                <div class="list">
+                    <table>
+                        <thead>
+                            <tr>
+
+                                <th>
+                                        <img  src="${resource(dir:'images/skin',file:'flag_red.png')}" alt="Flag" />
+                                </th>
+
+                                <th>Target Start Date</th>
+
+                                <th>Description</th>
+
+                                <th>Group</th>
+
+                                <th>Type</th>
+
+                                <th>Priority</th>
+
+                                <th>Status</th>
+
+                                <th></th>
+
+                            </tr>
+                        </thead>
+                        <tbody>
+                        <g:each in="${tasks}" status="i" var="taskInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                                <td class="idColumn" onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    <g:if test="${taskInstance.attentionFlag}">
+                                        <img  src="${resource(dir:'images/skin',file:'flag_red.png')}" alt="Flag" />
+                                    </g:if>
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    <g:formatDate date="${taskInstance.targetStartDate}" format="EEE, dd-MMM-yyyy"/>
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    <b>
+                                        Task #${fieldValue(bean:taskInstance, field:'id')}<br />
+                                        ${fieldValue(bean:taskInstance, field:'description')}
+                                    </b>
+                                    <br />
+                                    <br />
+                                    <g:if test="${taskInstance.primaryAsset}">
+                                        ${fieldValue(bean:taskInstance, field:'primaryAsset')}<br />
+                                    </g:if>
+                                    <g:each in="${taskInstance.assignedGroups}" status="j" var="assignedGroup">
+                                        ${assignedGroup.encodeAsHTML()}<br />
+                                    </g:each>
+                                    <g:each in="${taskInstance.assignedPersons}" status="k" var="assignedPerson">
+                                        ${assignedPerson.encodeAsHTML()}<br />
+                                    </g:each>
+                                    <g:each in="${taskInstance.entries}" status="m" var="entry">
+                                        <g:if test="${entry.entryType.id == 3}">
+                                            <em>${'WD: ' +entry.toShortString().encodeAsHTML()}</em><br />
+                                        </g:if>
+                                    </g:each>
+                                    <g:if test="${taskInstance.subTasks}">
+                                        Sub Tasks: ${taskInstance.subTasks.size()}<br />
+                                    </g:if>
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    ${fieldValue(bean:taskInstance, field:'taskGroup')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    ${fieldValue(bean:taskInstance, field:'taskType')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    ${fieldValue(bean:taskInstance, field:'taskPriority')}
+                                </td>
+
+                                <td onclick='window.location = "${request.getContextPath()}/taskDetailed/show/${taskInstance.id}"'>
+                                    ${fieldValue(bean:taskInstance, field:'taskStatus')}
+                                </td>
+
+                                <td class="notClickable">
+                                    <g:link action="show" id="${taskInstance.id}">
+                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                    </g:link>
+                                </td>
+
+                            </tr>
+                        </g:each>
+                        </tbody>
+                    </table>
+                </div>
+            </g:if>
+
+            <!-- Start Search Pane -->
+            <div class="overlayPane" id="searchPane" style="display:none;">
+                <h2>Search</h2>
+                <g:form method="post" controller="taskDetailed">
+                    <table>
+                        <tbody>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="date">Date:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <richui:dateChooser name="startDate" format="dd-MM-yyyy" value="${startDate}" />
+                                    to
+                                    <richui:dateChooser name="endDate" format="dd-MM-yyyy" value="${endDate}" />
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Task Status:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:checkBoxList name="taskStatusList"
+                                                                            from="${TaskStatus.findAllByIsActive(true)}"
+                                                                            value="${taskStatusList?.collect{it.id}}"
+                                                                            optionKey="id"
+                                                                            sortBy="name"
+                                                                            linkController="taskStatusDetailed"
+                                                                            linkAction="show"
+                                                                            height="150px"/>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label>Task Groups:</label>
+                                </td>
+                                <td valign="top" class="value">
+                                    <custom:checkBoxList name="taskGroups"
+                                                                            from="${TaskGroup.findAllByIsActive(true)}"
+                                                                            value="${taskGroups?.collect{it.id}}"
+                                                                            optionKey="id"
+                                                                            sortBy="name"
+                                                                            linkController="taskGroupDetailed"
+                                                                            linkAction="show"
+                                                                            height="150px"/>
+                                </td>
+                            </tr>
+
+                        </tbody>
+                    </table>
+                    <div class="buttons">
+                        <span class="button">
+                            <g:actionSubmit class="save" value="Update" action="workLoad" />
+                            <g:actionSubmit class="cancel" value="${g.message(code:'fp.tag.filterPane.button.cancel.text', default:'Cancel')}" onclick="return hideElement('searchPane');" />
+                        </span>
+                    </div>
+                </g:form>
+            </div> <!-- end search pane -->
+
+        </div> <!--body-->
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/create.gsp	(revision 753)
@@ -0,0 +1,62 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create TaskGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${taskGroupInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskGroupInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskGroupInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskGroupInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskGroupInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskGroupInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskGroupInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskGroupInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,66 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit TaskGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${taskGroupInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskGroupInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${taskGroupInstance?.id}" />
+                <input type="hidden" name="version" value="${taskGroupInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskGroupInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskGroupInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskGroupInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskGroupInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskGroupInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskGroupInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/list.gsp	(revision 753)
@@ -0,0 +1,69 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>TaskGroup List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${taskGroupInstanceList}" status="i" var="taskGroupInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/taskGroupDetailed/show/${taskGroupInstance.id}"'>
+                                    ${fieldValue(bean:taskGroupInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/taskGroupDetailed/show/${taskGroupInstance.id}"'>
+                                ${fieldValue(bean:taskGroupInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/taskGroupDetailed/show/${taskGroupInstance.id}"'>
+                                ${fieldValue(bean:taskGroupInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/taskGroupDetailed/show/${taskGroupInstance.id}"'>
+                                ${fieldValue(bean:taskGroupInstance, field:'isActive')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${taskGroupInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${taskGroupInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskGroupDetailed/show.gsp	(revision 753)
@@ -0,0 +1,61 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show TaskGroup</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskGroupInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskGroupInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskGroupInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskGroupInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${taskGroupInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskModificationType/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskModificationType/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskModificationType/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create TaskModificationType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskModificationType List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create TaskModificationType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskModificationTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskModificationTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskModificationTypeInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskModificationTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskModificationTypeInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskModificationTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskModificationTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskModificationTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskModificationType/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskModificationType/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskModificationType/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit TaskModificationType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskModificationType List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskModificationType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit TaskModificationType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskModificationTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskModificationTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${taskModificationTypeInstance?.id}" />
+                <input type="hidden" name="version" value="${taskModificationTypeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskModificationTypeInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskModificationTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskModificationTypeInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskModificationTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskModificationTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskModificationTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskModifications">Task Modifications:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskModificationTypeInstance,field:'taskModifications','errors')}">
+                                    
+<ul>
+<g:each var="t" in="${taskModificationTypeInstance?.taskModifications?}">
+    <li><g:link controller="taskModification" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="taskModification" params="['taskModificationType.id':taskModificationTypeInstance?.id]" action="create">Add TaskModification</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskModificationType/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskModificationType/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskModificationType/list.gsp	(revision 753)
@@ -0,0 +1,55 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>TaskModificationType List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New TaskModificationType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>TaskModificationType List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${taskModificationTypeInstanceList}" status="i" var="taskModificationTypeInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${taskModificationTypeInstance.id}">${fieldValue(bean:taskModificationTypeInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:taskModificationTypeInstance, field:'name')}</td>
+                        
+                            <td>${fieldValue(bean:taskModificationTypeInstance, field:'description')}</td>
+                        
+                            <td>${fieldValue(bean:taskModificationTypeInstance, field:'isActive')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${taskModificationTypeInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskModificationType/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskModificationType/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskModificationType/show.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show TaskModificationType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskModificationType List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskModificationType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show TaskModificationType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskModificationTypeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskModificationTypeInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskModificationTypeInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskModificationTypeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Task Modifications:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="t" in="${taskModificationTypeInstance.taskModifications}">
+                                    <li><g:link controller="taskModification" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${taskModificationTypeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskPriority/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskPriority/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskPriority/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create TaskPriority</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskPriority List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create TaskPriority</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskPriorityInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskPriorityInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskPriorityInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskPriorityInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskPriorityInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskPriorityInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskPriorityInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskPriorityInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskPriority/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskPriority/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskPriority/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit TaskPriority</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskPriority List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskPriority</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit TaskPriority</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskPriorityInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskPriorityInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${taskPriorityInstance?.id}" />
+                <input type="hidden" name="version" value="${taskPriorityInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskPriorityInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskPriorityInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskPriorityInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskPriorityInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskPriorityInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskPriorityInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="tasks">Tasks:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskPriorityInstance,field:'tasks','errors')}">
+                                    
+<ul>
+<g:each var="t" in="${taskPriorityInstance?.tasks?}">
+    <li><g:link controller="task" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="task" params="['taskPriority.id':taskPriorityInstance?.id]" action="create">Add Task</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskPriority/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskPriority/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskPriority/list.gsp	(revision 753)
@@ -0,0 +1,55 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>TaskPriority List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New TaskPriority</g:link></span>
+        </div>
+        <div class="body">
+            <h1>TaskPriority List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${taskPriorityInstanceList}" status="i" var="taskPriorityInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${taskPriorityInstance.id}">${fieldValue(bean:taskPriorityInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:taskPriorityInstance, field:'name')}</td>
+                        
+                            <td>${fieldValue(bean:taskPriorityInstance, field:'description')}</td>
+                        
+                            <td>${fieldValue(bean:taskPriorityInstance, field:'isActive')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${taskPriorityInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskPriority/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskPriority/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskPriority/show.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show TaskPriority</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskPriority List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskPriority</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show TaskPriority</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskPriorityInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskPriorityInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskPriorityInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskPriorityInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Tasks:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="t" in="${taskPriorityInstance.tasks}">
+                                    <li><g:link controller="task" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${taskPriorityInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskProcedure/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskProcedure/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskProcedure/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create TaskProcedure</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskProcedure List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create TaskProcedure</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskProcedureInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskProcedureInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="75" id="name" name="name" value="${fieldValue(bean:taskProcedureInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskProcedureInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskProcedureInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskProcedure/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskProcedure/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskProcedure/edit.gsp	(revision 753)
@@ -0,0 +1,100 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit TaskProcedure</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskProcedure List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskProcedure</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit TaskProcedure</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskProcedureInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskProcedureInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${taskProcedureInstance?.id}" />
+                <input type="hidden" name="version" value="${taskProcedureInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="75" id="name" name="name" value="${fieldValue(bean:taskProcedureInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskProcedureInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskProcedureInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="maintenanceActions">Maintenance Actions:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'maintenanceActions','errors')}">
+                                    
+<ul>
+<g:each var="m" in="${taskProcedureInstance?.maintenanceActions?}">
+    <li><g:link controller="maintenanceAction" action="show" id="${m.id}">${m?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="maintenanceAction" params="['taskProcedure.id':taskProcedureInstance?.id]" action="create">Add MaintenanceAction</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="tasks">Tasks:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'tasks','errors')}">
+                                    
+<ul>
+<g:each var="t" in="${taskProcedureInstance?.tasks?}">
+    <li><g:link controller="task" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="task" params="['taskProcedure.id':taskProcedureInstance?.id]" action="create">Add Task</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskProcedure/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskProcedure/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskProcedure/list.gsp	(revision 753)
@@ -0,0 +1,55 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>TaskProcedure List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New TaskProcedure</g:link></span>
+        </div>
+        <div class="body">
+            <h1>TaskProcedure List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${taskProcedureInstanceList}" status="i" var="taskProcedureInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${taskProcedureInstance.id}">${fieldValue(bean:taskProcedureInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:taskProcedureInstance, field:'name')}</td>
+                        
+                            <td>${fieldValue(bean:taskProcedureInstance, field:'description')}</td>
+                        
+                            <td>${fieldValue(bean:taskProcedureInstance, field:'isActive')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${taskProcedureInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskProcedure/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskProcedure/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskProcedure/show.gsp	(revision 753)
@@ -0,0 +1,90 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show TaskProcedure</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskProcedure List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskProcedure</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show TaskProcedure</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Maintenance Actions:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="m" in="${taskProcedureInstance.maintenanceActions}">
+                                    <li><g:link controller="maintenanceAction" action="show" id="${m.id}">${m?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Tasks:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="t" in="${taskProcedureInstance.tasks}">
+                                    <li><g:link controller="task" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${taskProcedureInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/create.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create TaskProcedure</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskProcedureInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskProcedureInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+            <input type="hidden" name="taskInstance.id" value="${taskInstance?.id}" />
+
+                <div class="dialog">
+                    <table>
+                        <tbody>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'name','errors')}">
+                                    <input type="text"  class="description" maxlength="75" id="name" name="name" value="${fieldValue(bean:taskProcedureInstance,field:'name')}"/>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'description','errors')}">
+                                    <input type="text"  class="description" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskProcedureInstance,field:'description')}"/>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskProcedureInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr>
+
+                            <g:if test="${taskInstance}">
+                                <tr class="prop">
+                                    <td valign="top" class="name">
+                                        <label for="taskInstance">Linking with Task:</label>
+                                    </td>
+                                    <td valign="top" name="taskInstance" class="value">
+                                        ${taskInstance}
+                                    </td>
+                                </tr>
+                            </g:if>
+
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,99 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit TaskProcedure</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskProcedureInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskProcedureInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${taskProcedureInstance?.id}" />
+                <input type="hidden" name="version" value="${taskProcedureInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'name','errors')}">
+                                    <input type="text"  class="description" maxlength="75" id="name" name="name" value="${fieldValue(bean:taskProcedureInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'description','errors')}">
+                                    <input type="text"  class="description" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskProcedureInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskProcedureInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="maintenanceActions">Maintenance Actions:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'maintenanceActions','errors')}">
+                                    
+<ul>
+<g:each var="m" in="${taskProcedureInstance?.maintenanceActions?}">
+    <li><g:link controller="maintenanceActionDetailed" action="show" id="${m.id}">${m?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="maintenanceActionDetailed" params="['taskProcedure.id':taskProcedureInstance?.id]" action="create">+Add MaintenanceAction</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="tasks">Tasks:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskProcedureInstance,field:'tasks','errors')}">
+                                    
+<ul>
+<g:each var="t" in="${taskProcedureInstance?.tasks?}">
+    <li><g:link controller="taskDetailed" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="taskDetailed" params="['taskProcedure.id':taskProcedureInstance?.id]" action="create">+Add Task</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/list.gsp	(revision 753)
@@ -0,0 +1,88 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>TaskProcedure List</title>
+        <filterpane:includes />
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <filterpane:currentCriteria domainBean="TaskProcedure"
+                                    action="list"
+                                    dateFormat="EEE, dd-MMM-yyyy"
+                                    removeImgDir="images" 
+                                    removeImgFile="bullet_delete.png"
+                                    title="Search"/>
+
+            <div class="paginateButtons">
+                <span class="searchButtons">
+                    <filterpane:filterButton text="Search" appliedText="Change Search" />
+                </span>
+                Results: ${taskProcedureInstanceList.size()} / ${taskProcedureInstanceTotal}
+            </div>
+
+
+            <g:if test="${taskProcedureInstanceList.size() > 0}">
+                <div class="list">
+                    <table>
+                        <thead>
+                            <tr>
+                            
+                                <g:sortableColumn property="id" title="Id"  params="${filterParams}" />
+                            
+                                <g:sortableColumn property="name" title="Name"  params="${filterParams}" />
+                            
+                                <g:sortableColumn property="description" title="Description"  params="${filterParams}" />
+                            
+                                <g:sortableColumn property="isActive" title="Is Active"  params="${filterParams}" />
+
+                                <th></th>
+                            
+                            </tr>
+                        </thead>
+                        <tbody>
+                        <g:each in="${taskProcedureInstanceList}" status="i" var="taskProcedureInstance">
+                            <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}" onclick='window.location = "${request.getContextPath()}/taskProcedureDetailed/show/${taskProcedureInstance.id}"'/>
+                            
+                                <td>${fieldValue(bean:taskProcedureInstance, field:'id')}</td>
+                            
+                                <td>${fieldValue(bean:taskProcedureInstance, field:'name')}</td>
+                            
+                                <td>${fieldValue(bean:taskProcedureInstance, field:'description')}</td>
+                            
+                                <td>${fieldValue(bean:taskProcedureInstance, field:'isActive')}</td>
+                                
+                                <td>
+                                    <g:link action="show" id="${taskProcedureInstance.id}">
+                                        <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                    </g:link>
+                                </td>
+                            
+                            </tr>
+                        </g:each>
+                        </tbody>
+                    </table>
+                </div>
+            </g:if>
+
+            <div class="paginateButtons">
+                <g:paginate total="${taskProcedureInstanceTotal}" params="${filterParams}" />
+            </div>
+
+            <filterpane:filterPane domainBean="TaskProcedure"
+                                    title="Search"
+                                    action="list"
+                                    class="overlayPane"
+                                    excludeProperties="" />
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskProcedureDetailed/show.gsp	(revision 753)
@@ -0,0 +1,89 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show TaskProcedure</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskProcedureInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Maintenance Actions:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="m" in="${taskProcedureInstance.maintenanceActions}">
+                                    <li><g:link controller="maintenanceActionDetailed" action="show" id="${m.id}">${m?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Tasks:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="t" in="${taskProcedureInstance.tasks}">
+                                    <li><g:link controller="taskDetailed" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${taskProcedureInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/create.gsp	(revision 753)
@@ -0,0 +1,128 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create TaskRecurringSchedule</title>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Create Recurring Schedule</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskRecurringScheduleInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskRecurringScheduleInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <g:hiddenField name="task.id" value="${taskRecurringScheduleInstance.task.id}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="recForTask">Recurring Schedule for Task:</label>
+                                </td>
+                                <td valign="top" name="recForTask" class="value">
+                                    <g:link controller="taskDetailed" action="show" id="${taskRecurringScheduleInstance?.task?.id}">${taskRecurringScheduleInstance?.task?.encodeAsHTML()}</g:link>
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="nextTargetStartDate">Next Target Start Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskRecurringScheduleInstance,field:'nextTargetStartDate','errors')}">
+                                    <richui:dateChooser name="nextTargetStartDate" format="dd-MM-yyyy" value="${taskRecurringScheduleInstance?.nextTargetStartDate}" />
+                                    <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.nextTargetStartDate" />
+                                </td>
+                            </tr>   
+                      
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="recurEvery">Recur Every:</label>
+                                </td>
+                                <td valign="top" class="value" >
+                                    <input type="text" class="time ${hasErrors(bean:taskRecurringScheduleInstance,field:'recurEvery','errors')}"
+                                        id="recurEvery" name="recurEvery" value="${fieldValue(bean:taskRecurringScheduleInstance,field:'recurEvery')}" />
+                                    <g:select optionKey="id" from="${Period.list()}" name="recurPeriod.id" value="${taskRecurringScheduleInstance?.recurPeriod?.id}" ></g:select>
+                                    <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.recurEvery" />
+                                </td>
+                            </tr>   
+                      
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskDuration">Task Duration:</label>
+                                </td>
+                                <td valign="top" class="value" >
+                                    <input type="text" class="time ${hasErrors(bean:taskRecurringScheduleInstance,field:'taskDuration','errors')}"
+                                        id="taskDuration" name="taskDuration" value="${fieldValue(bean:taskRecurringScheduleInstance,field:'taskDuration')}" />
+                                    <g:select optionKey="id" from="${Period.list()}" name="taskDurationPeriod.id" value="${taskRecurringScheduleInstance?.taskDurationPeriod?.id}" ></g:select>
+                                    <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.taskDuration" />
+                                </td>
+                            </tr>   
+                      
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="generateAhead">Generate Ahead:</label>
+                                </td>
+                                <td valign="top" class="value" >
+                                    <input type="text" class="time ${hasErrors(bean:taskRecurringScheduleInstance,field:'generateAhead','errors')}"
+                                        id="generateAhead" name="generateAhead" value="${fieldValue(bean:taskRecurringScheduleInstance,field:'generateAhead')}" />
+                                        ${Period.get(1).encodeAsHTML()}
+                                        <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.generateAhead" />
+                                </td>
+                            </tr>
+                      
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="maxSubTasks">Max Sub Tasks:</label>
+                                </td>
+                                <td valign="top" class="value" >
+                                    <input type="text" class="time ${hasErrors(bean:taskRecurringScheduleInstance,field:'maxSubTasks','errors')}"
+                                        id="maxSubTasks" name="maxSubTasks" value="${fieldValue(bean:taskRecurringScheduleInstance,field:'maxSubTasks')}" />
+                                        <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.maxSubTasks" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="useTargetCompletionDate">Use Target Completion Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskRecurringScheduleInstance,field:'useTargetCompletionDate','errors')}">
+                                    <g:checkBox name="useTargetCompletionDate"
+                                                            value="${taskRecurringScheduleInstance?.useTargetCompletionDate}" >
+                                    </g:checkBox>
+                                    <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.useTargetCompletionDate" />
+                                    <g:formatDate date="${taskRecurringScheduleInstance.task.targetCompletionDate}"
+                                                                    format="EEE, dd-MMM-yyyy"/>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="enabled">Enabled:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskRecurringScheduleInstance,field:'enabled','errors')}">
+                                    <g:checkBox name="enabled" value="${taskRecurringScheduleInstance?.enabled}" ></g:checkBox>
+                                        <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.enabled" />
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,130 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit TaskRecurringSchedule</title>
+        <resource:dateChooser />
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Edit Recurring Schedule</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskRecurringScheduleInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskRecurringScheduleInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${taskRecurringScheduleInstance?.id}" />
+                <input type="hidden" name="version" value="${taskRecurringScheduleInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="recForTask">Recurring Schedule for Task:</label>
+                                </td>
+                                <td valign="top" name="recForTask" class="value">
+                                    <g:link controller="taskDetailed" action="show" id="${taskRecurringScheduleInstance?.task?.id}">${taskRecurringScheduleInstance?.task?.encodeAsHTML()}</g:link>
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="enabled">Enabled:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskRecurringScheduleInstance,field:'enabled','errors')}">
+                                    <g:checkBox name="enabled" value="${taskRecurringScheduleInstance?.enabled}" ></g:checkBox>
+                                        <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.enabled" />
+                                </td>
+                            </tr>
+                            
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="nextTargetStartDate">Next Target Start Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskRecurringScheduleInstance,field:'nextTargetStartDate','errors')}">
+                                    <richui:dateChooser name="nextTargetStartDate" format="dd-MM-yyyy" value="${taskRecurringScheduleInstance?.nextTargetStartDate}" />
+                                    <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.nextTargetStartDate" />
+                                </td>
+                            </tr>   
+                      
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="recurEvery">Recur Every:</label>
+                                </td>
+                                <td valign="top" class="value" >
+                                    <input type="text" class="time ${hasErrors(bean:taskRecurringScheduleInstance,field:'recurEvery','errors')}"
+                                        id="recurEvery" name="recurEvery" value="${fieldValue(bean:taskRecurringScheduleInstance,field:'recurEvery')}" />
+                                    <g:select optionKey="id" from="${Period.list()}" name="recurPeriod.id" value="${taskRecurringScheduleInstance?.recurPeriod?.id}" ></g:select>
+                                    <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.recurEvery" />
+                                </td>
+                            </tr>   
+                      
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="taskDuration">Task Duration:</label>
+                                </td>
+                                <td valign="top" class="value" >
+                                    <input type="text" class="time ${hasErrors(bean:taskRecurringScheduleInstance,field:'taskDuration','errors')}"
+                                        id="taskDuration" name="taskDuration" value="${fieldValue(bean:taskRecurringScheduleInstance,field:'taskDuration')}" />
+                                    <g:select optionKey="id" from="${Period.list()}" name="taskDurationPeriod.id" value="${taskRecurringScheduleInstance?.taskDurationPeriod?.id}" ></g:select>
+                                    <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.taskDuration" />
+                                </td>
+                            </tr>       
+                      
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="generateAhead">Generate Ahead:</label>
+                                </td>
+                                <td valign="top" class="value" >
+                                    <input type="text" class="time ${hasErrors(bean:taskRecurringScheduleInstance,field:'generateAhead','errors')}"
+                                        id="generateAhead" name="generateAhead" value="${fieldValue(bean:taskRecurringScheduleInstance,field:'generateAhead')}" />
+                                        ${Period.get(1).encodeAsHTML()}
+                                        <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.generateAhead" />
+                                </td>
+                            </tr>
+                      
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="maxSubTasks">Max Sub Tasks:</label>
+                                </td>
+                                <td valign="top" class="value" >
+                                    <input type="text" class="time ${hasErrors(bean:taskRecurringScheduleInstance,field:'maxSubTasks','errors')}"
+                                        id="maxSubTasks" name="maxSubTasks" value="${fieldValue(bean:taskRecurringScheduleInstance,field:'maxSubTasks')}" />
+                                        <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.maxSubTasks" />
+                                </td>
+                            </tr>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="useTargetCompletionDate">Use Target Completion Date:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskRecurringScheduleInstance,field:'useTargetCompletionDate','errors')}">
+                                    <g:checkBox name="useTargetCompletionDate"
+                                                                value="${taskRecurringScheduleInstance?.useTargetCompletionDate}" >
+                                    </g:checkBox>
+                                    <g:helpBalloon class="helpballoon" code="taskRecurringSchedule.useTargetCompletionDate" />
+                                    <g:formatDate date="${taskRecurringScheduleInstance.task.targetCompletionDate}"
+                                                                    format="EEE, dd-MMM-yyyy"/>
+                                </td>
+                            </tr>
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+<!--                     <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span> -->
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/list.gsp	(revision 753)
@@ -0,0 +1,78 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>TaskRecurringSchedule List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New TaskRecurringSchedule</g:link></span>
+        </div>
+        <div class="body">
+            <h1>TaskRecurringSchedule List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="taskId" title="Recurring Schedule for Task" />
+                        
+                   	        <g:sortableColumn property="recurEvery" title="Recur Every" />
+                   	        
+                   	        <g:sortableColumn property="recurPeriod" title="Recur Period" />
+                   	        
+                   	        <g:sortableColumn property="enabled" title="Enabled" />
+
+                            <th></th>
+                   	    
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${taskRecurringScheduleInstanceList}" status="i" var="taskRecurringScheduleInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/taskRecurringScheduleDetailed/show/${taskRecurringScheduleInstance.id}"'>
+                                ${fieldValue(bean:taskRecurringScheduleInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/taskRecurringScheduleDetailed/show/${taskRecurringScheduleInstance.id}"'>
+                                ${fieldValue(bean:taskRecurringScheduleInstance, field:'task')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/taskRecurringScheduleDetailed/show/${taskRecurringScheduleInstance.id}"'>
+                                ${fieldValue(bean:taskRecurringScheduleInstance, field:'recurEvery')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/taskRecurringScheduleDetailed/show/${taskRecurringScheduleInstance.id}"'>
+                                ${fieldValue(bean:taskRecurringScheduleInstance, field:'recurPeriod')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/taskRecurringScheduleDetailed/show/${taskRecurringScheduleInstance.id}"'>
+                                ${fieldValue(bean:taskRecurringScheduleInstance, field:'enabled')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${taskRecurringScheduleInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${taskRecurringScheduleInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskRecurringScheduleDetailed/show.gsp	(revision 753)
@@ -0,0 +1,167 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show TaskRecurringSchedule</title>
+    </head>
+    <body>
+        <div class="nav">
+            <h1>Show Recurring Schedule</h1>
+        </div>
+        <div class="body">
+            <g:if test="${flash.message}">
+                <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+                        <tr class="prop">
+                            <td valign="top" class="name">Recurring Schedule for task:</td>
+
+                            <td valign="top" class="value">
+                                <g:link controller="taskDetailed" action="show" id="${taskRecurringScheduleInstance.task?.id}">
+                                    ${taskRecurringScheduleInstance.task.encodeAsHTML()}
+                                </g:link>
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name"></td>
+
+                            <td valign="top" class="value">${taskRecurringScheduleInstance.encodeAsHTML()}</td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Enabled:</td>
+
+                            <td valign="top" class="value">${fieldValue(bean:taskRecurringScheduleInstance, field:'enabled')}</td>
+                        </tr>
+
+                        <g:if test="${taskRecurringScheduleInstance.useTargetCompletionDate}" >
+                            <tr class="prop">
+                                <td valign="top" class="name">Task Target Completion:</td>
+
+                                <td valign="top" class="value">
+                                    <g:formatDate date="${taskRecurringScheduleInstance.task.targetCompletionDate}"
+                                                                    format="EEE, dd-MMM-yyyy"/>
+                                </td>
+                            </tr>
+                        </g:if>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Next Generation Date:</td>
+
+                            <td valign="top" class="value">
+                                <g:formatDate date="${taskRecurringScheduleInstance.nextGenerationDate}" format="EEE, dd-MMM-yyyy"/>
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Generate Ahead:</td>
+
+                            <td valign="top" class="value">
+                                ${taskRecurringScheduleInstance.generateAhead} ${Period.get(1).encodeAsHTML()}
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Next Target Start Date:</td>
+
+                            <td valign="top" class="value">
+                                <g:formatDate date="${taskRecurringScheduleInstance.nextTargetStartDate}" format="EEE, dd-MMM-yyyy"/>
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Task Duration:</td>
+
+                            <td valign="top" class="value">
+                                ${taskRecurringScheduleInstance.taskDuration} ${taskRecurringScheduleInstance.taskDurationPeriod}
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Next Target Completion Date:</td>
+
+                            <td valign="top" class="value">
+                                <g:formatDate date="${taskRecurringScheduleInstance.nextTargetCompletionDate}" format="EEE, dd-MMM-yyyy"/>
+                            </td>
+                        </tr>
+
+                    </tbody>
+                </table>
+                <table>
+                    <tbody>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Note:</td>
+
+                            <td valign="top" class="value">
+                                Recurring Schedules are reviewed and Sub Tasks generated every ${grailsApplication.config.taskRecurringScheduleJob.repeatInterval.encodeAsHTML()} seconds.
+                            </td>
+                        </tr>
+
+                        <tr class="prop">
+                            <td valign="top" class="name">Sub Tasks Generated:</td>
+
+                            <td valign="top" class="value">
+                                ${fieldValue(bean:taskRecurringScheduleInstance, field:'subTasksGenerated')}
+                            </td>
+                        </tr>
+
+                        <g:if test="${taskRecurringScheduleInstance.maxSubTasks > 0}" >
+                            <tr class="prop">
+                                <td valign="top" class="name">Max Sub Tasks:</td>
+
+                                <td valign="top" class="value">
+                                    ${fieldValue(bean:taskRecurringScheduleInstance, field:'maxSubTasks')}
+                                </td>
+                            </tr>
+                        </g:if>
+
+                        <g:if test="${taskRecurringScheduleInstance.lastGeneratedSubTask}">
+
+                            <tr class="prop">
+                                <td valign="top" class="name">Last Generated Sub Task:</td>
+
+                                <td valign="top" class="value">
+                                    <g:link controller="taskDetailed" action="show" id="${taskRecurringScheduleInstance.lastGeneratedSubTask?.id}">
+                                        ${taskRecurringScheduleInstance.lastGeneratedSubTask?.encodeAsHTML()}
+                                    </g:link>
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name"></td>
+
+                                <td valign="top" class="value">
+                                        ${TaskModification.findByTaskAndTaskModificationType(taskRecurringScheduleInstance.lastGeneratedSubTask, TaskModificationType.get(1))}
+                                </td>
+                            </tr>
+
+                            <tr class="prop">
+                                <td valign="top" class="name"></td>
+
+                                <td valign="top" class="value">
+                                        With target start date:
+                                        <g:formatDate date="${taskRecurringScheduleInstance.lastGeneratedSubTask?.targetStartDate}" format="EEE, dd-MMM-yyyy"/>
+                                </td>
+                            </tr>
+
+                        </g:if>
+
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${taskRecurringScheduleInstance.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+<!--                     <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span> -->
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskStatus/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskStatus/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskStatus/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create TaskStatus</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskStatus List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create TaskStatus</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskStatusInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskStatusInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskStatusInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskStatusInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskStatusInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskStatusInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskStatusInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskStatusInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskStatus/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskStatus/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskStatus/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit TaskStatus</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskStatus List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskStatus</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit TaskStatus</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskStatusInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskStatusInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${taskStatusInstance?.id}" />
+                <input type="hidden" name="version" value="${taskStatusInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskStatusInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskStatusInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskStatusInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskStatusInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskStatusInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskStatusInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="tasks">Tasks:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskStatusInstance,field:'tasks','errors')}">
+                                    
+<ul>
+<g:each var="t" in="${taskStatusInstance?.tasks?}">
+    <li><g:link controller="task" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="task" params="['taskStatus.id':taskStatusInstance?.id]" action="create">Add Task</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskStatus/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskStatus/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskStatus/list.gsp	(revision 753)
@@ -0,0 +1,55 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>TaskStatus List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New TaskStatus</g:link></span>
+        </div>
+        <div class="body">
+            <h1>TaskStatus List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${taskStatusInstanceList}" status="i" var="taskStatusInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${taskStatusInstance.id}">${fieldValue(bean:taskStatusInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:taskStatusInstance, field:'name')}</td>
+                        
+                            <td>${fieldValue(bean:taskStatusInstance, field:'description')}</td>
+                        
+                            <td>${fieldValue(bean:taskStatusInstance, field:'isActive')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${taskStatusInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskStatus/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskStatus/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskStatus/show.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show TaskStatus</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskStatus List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskStatus</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show TaskStatus</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskStatusInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskStatusInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskStatusInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskStatusInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Tasks:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="t" in="${taskStatusInstance.tasks}">
+                                    <li><g:link controller="task" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${taskStatusInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskType/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskType/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskType/create.gsp	(revision 753)
@@ -0,0 +1,64 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create TaskType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskType List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create TaskType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskTypeInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskTypeInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskType/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskType/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskType/edit.gsp	(revision 753)
@@ -0,0 +1,84 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit TaskType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskType List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit TaskType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <g:hasErrors bean="${taskTypeInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${taskTypeInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${taskTypeInstance?.id}" />
+                <input type="hidden" name="version" value="${taskTypeInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskTypeInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:taskTypeInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskTypeInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:taskTypeInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskTypeInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${taskTypeInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="tasks">Tasks:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:taskTypeInstance,field:'tasks','errors')}">
+                                    
+<ul>
+<g:each var="t" in="${taskTypeInstance?.tasks?}">
+    <li><g:link controller="task" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+</g:each>
+</ul>
+<g:link controller="task" params="['taskType.id':taskTypeInstance?.id]" action="create">Add Task</g:link>
+
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskType/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskType/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskType/list.gsp	(revision 753)
@@ -0,0 +1,55 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>TaskType List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New TaskType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>TaskType List</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${taskTypeInstanceList}" status="i" var="taskTypeInstance">
+                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
+                        
+                            <td><g:link action="show" id="${taskTypeInstance.id}">${fieldValue(bean:taskTypeInstance, field:'id')}</g:link></td>
+                        
+                            <td>${fieldValue(bean:taskTypeInstance, field:'name')}</td>
+                        
+                            <td>${fieldValue(bean:taskTypeInstance, field:'description')}</td>
+                        
+                            <td>${fieldValue(bean:taskTypeInstance, field:'isActive')}</td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${taskTypeInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/taskType/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/taskType/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/taskType/show.gsp	(revision 753)
@@ -0,0 +1,77 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show TaskType</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">TaskType List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New TaskType</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show TaskType</h1>
+            <g:if test="${flash.message}">
+            <div class="message">${flash.message}</div>
+            </g:if>
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskTypeInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskTypeInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskTypeInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:taskTypeInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Tasks:</td>
+                            
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="t" in="${taskTypeInstance.tasks}">
+                                    <li><g:link controller="task" action="show" id="${t.id}">${t?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${taskTypeInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/create.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/create.gsp	(revision 753)
@@ -0,0 +1,62 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create UnitOfMeasure</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${unitOfMeasureInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${unitOfMeasureInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" >
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:unitOfMeasureInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:unitOfMeasureInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:unitOfMeasureInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:unitOfMeasureInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:unitOfMeasureInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${unitOfMeasureInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/edit.gsp	(revision 753)
@@ -0,0 +1,66 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit UnitOfMeasure</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="${unitOfMeasureInstance}">
+            <div class="errors">
+                <g:renderErrors bean="${unitOfMeasureInstance}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" >
+                <input type="hidden" name="id" value="${unitOfMeasureInstance?.id}" />
+                <input type="hidden" name="version" value="${unitOfMeasureInstance?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="name">Name:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:unitOfMeasureInstance,field:'name','errors')}">
+                                    <input type="text" maxlength="50" id="name" name="name" value="${fieldValue(bean:unitOfMeasureInstance,field:'name')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="description">Description:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:unitOfMeasureInstance,field:'description','errors')}">
+                                    <input type="text" maxlength="100" id="description" name="description" value="${fieldValue(bean:unitOfMeasureInstance,field:'description')}"/>
+                                </td>
+                            </tr> 
+                        
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="isActive">Is Active:</label>
+                                </td>
+                                <td valign="top" class="value ${hasErrors(bean:unitOfMeasureInstance,field:'isActive','errors')}">
+                                    <g:checkBox name="isActive" value="${unitOfMeasureInstance?.isActive}" ></g:checkBox>
+                                </td>
+                            </tr> 
+                        
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/list.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/list.gsp	(revision 753)
@@ -0,0 +1,69 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>UnitOfMeasure List</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        
+                   	        <g:sortableColumn property="id" title="Id" />
+                        
+                   	        <g:sortableColumn property="name" title="Name" />
+                        
+                   	        <g:sortableColumn property="description" title="Description" />
+                        
+                   	        <g:sortableColumn property="isActive" title="Is Active" />
+
+                            <th></th>
+                        
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="${unitOfMeasureInstanceList}" status="i" var="unitOfMeasureInstance">
+                        <tr class="${(i % 2) == 0 ? 'clickableOdd' : 'clickableEven'}"/>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/unitOfMeasureDetailed/show/${unitOfMeasureInstance.id}"'>
+                                    ${fieldValue(bean:unitOfMeasureInstance, field:'id')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/unitOfMeasureDetailed/show/${unitOfMeasureInstance.id}"'>
+                                ${fieldValue(bean:unitOfMeasureInstance, field:'name')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/unitOfMeasureDetailed/show/${unitOfMeasureInstance.id}"'>
+                                ${fieldValue(bean:unitOfMeasureInstance, field:'description')}
+                            </td>
+                        
+                            <td onclick='window.location = "${request.getContextPath()}/unitOfMeasureDetailed/show/${unitOfMeasureInstance.id}"'>
+                                ${fieldValue(bean:unitOfMeasureInstance, field:'isActive')}
+                            </td>
+
+                            <td class="notClickable">
+                                <g:link action="show" id="${unitOfMeasureInstance.id}">
+                                    <img  src="${resource(dir:'images/skin',file:'database_go.png')}" alt="Show" />
+                                </g:link>
+                            </td>
+                        
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="${unitOfMeasureInstanceTotal}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/show.gsp
===================================================================
--- branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/grails-app/views/unitOfMeasureDetailed/show.gsp	(revision 753)
@@ -0,0 +1,61 @@
+
+
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show UnitOfMeasure</title>
+        <nav:resources override="true"/>
+    </head>
+    <body>
+        <div class="nav">
+            <nav:renderSubItems group="navAlt"/>
+        </div>
+        <div class="body">
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Id:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:unitOfMeasureInstance, field:'id')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Name:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:unitOfMeasureInstance, field:'name')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Description:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:unitOfMeasureInstance, field:'description')}</td>
+                            
+                        </tr>
+                    
+                        <tr class="prop">
+                            <td valign="top" class="name">Is Active:</td>
+                            
+                            <td valign="top" class="value">${fieldValue(bean:unitOfMeasureInstance, field:'isActive')}</td>
+                            
+                        </tr>
+                    
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="${unitOfMeasureInstance?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/scripts/UpdateRev.groovy
===================================================================
--- branches/features/taskProcedureRework/scripts/UpdateRev.groovy	(revision 753)
+++ branches/features/taskProcedureRework/scripts/UpdateRev.groovy	(revision 753)
@@ -0,0 +1,6 @@
+
+includeTargets << new File("${basedir}/scripts/_UpdateRev.groovy")
+
+target(default: "Update the app.vcsRevision property in application.properties and metadata.") { 
+    depends(updateVcsRevision)
+}
Index: branches/features/taskProcedureRework/scripts/_Events.groovy
===================================================================
--- branches/features/taskProcedureRework/scripts/_Events.groovy	(revision 753)
+++ branches/features/taskProcedureRework/scripts/_Events.groovy	(revision 753)
@@ -0,0 +1,9 @@
+
+includeTargets << new File("${basedir}/scripts/_UpdateRev.groovy")
+
+eventCompileStart = { msg ->
+    if(System.getProperty("grails.env") != "test") {
+        println "Compile started, checking VCS Revision."
+        updateVcsRevision()
+    }
+}
Index: branches/features/taskProcedureRework/scripts/_UpdateRev.groovy
===================================================================
--- branches/features/taskProcedureRework/scripts/_UpdateRev.groovy	(revision 753)
+++ branches/features/taskProcedureRework/scripts/_UpdateRev.groovy	(revision 753)
@@ -0,0 +1,171 @@
+import org.tmatesoft.svn.core.wc.*
+
+//includeTargets << grailsScript("Init")
+
+/**
+* Check and update the app.vcsRevision property in application.properties file and metadata.
+* May be run directly by `grails update-rev` and normally run by _Events.groovy and eventCompileStart.
+* The revision in the properties file is checked against the version control system (VCS) revision
+* and updated if required.
+* The VCS revision is written to the properties file so that it is available in the compiled war.
+* The compile is intentionally allowed to go ahead if a handled exception occurs.
+* VCS currently supported: subversion.
+*/
+target(updateVcsRevision: "Check and update the app.vcsRevision property in application.properties file and metadata.") {
+
+    def result = [:]
+
+    // Properties file.
+    def url = basedir + "/application.properties"
+    def propertiesFile = new File(url)
+
+    def fail = { Map m ->
+        updateInMemoryMetadata('Unknown')
+        def writeResult = writePropertiesFileRevision(propertiesFile, 'Unknown')
+        if(writeResult.error) {
+            m.code= writeResult.error.code
+            m.args= writeResult.error.args
+        }
+
+        result.error = [ code: m.code, args: m.args ]
+        println "Error: UpdateRev script: " + result.error
+        return result
+    }
+
+    // Get propertiesFile revision.
+    def properitesFileResult = getPropertiesFileRevision(propertiesFile)
+    if(properitesFileResult.error)
+        return fail(code: properitesFileResult.error.code, args: properitesFileResult.error.args)
+
+    // Get VCS revision.
+    def vcsResult = getVcsRevision()
+    if(vcsResult.error)
+        return fail(code: vcsResult.error.code, args: vcsResult.error.args)
+
+    // Compare and update.
+    if(properitesFileResult.revision != vcsResult.revision) {
+
+        println "app.vcsRevision = "+properitesFileResult.revision +', VCS Revision = '+vcsResult.revision
+
+        updateInMemoryMetadata(vcsResult.revision)
+
+        // Update application.properties file.
+        def writeResult = writePropertiesFileRevision(propertiesFile, vcsResult.revision)
+        if(writeResult.error)
+            return fail(code: writeResult.error.code, args: writeResult.error.args)
+
+    } // if(rev != rev)
+    else {
+        println "VCS Revisions match: app.vcsRevision = ${properitesFileResult.revision}, VCS Revision = ${vcsResult.revision}."
+    }
+
+    // Success.
+    return result
+
+} // updateVcsRevision()
+
+/**
+* Get the app.vcsRevision property from properties file.
+* @retuns A map containing revision and lineNumber otherwise an error map.
+*/
+def getPropertiesFileRevision(propertiesFile) {
+    def result = [:]
+
+    def fail = { Map m ->
+        result.error = [ code: m.code, args: m.args ]
+        return result
+    }
+
+    if(!propertiesFile.isFile())
+        return fail(code:"application.properties.file.not.found", args:[propertiesFile.getAbsoluteFile()])
+
+    propertiesFile.eachLine { line, lineNumber ->
+        // app.vcsRevision=$Rev: NUM $
+        if ( line =~ '^app.vcsRevision.' ) {
+            if(line.size() > 23) {
+                result.revision = line[22..-3]
+                result.lineNumber = lineNumber
+            }
+        }
+    }
+
+    if(!result.revision || !result.lineNumber)
+        return fail(code:"app.vcsRevision.not.found")
+
+    // Success.
+    return result
+
+} // getAppRevision()
+
+/**
+* Get the working copy's base revision from SVN.
+* @retuns A map containing revision otherwise an error map.
+*/
+def getVcsRevision() {
+    def result = [:]
+
+    def fail = { Map m ->
+        result.error = [ code: m.code, args: m.args ]
+        return result
+    }
+
+    def wc = new File(basedir)
+        if(!wc.isDirectory())
+            return fail(code:"vcs.working.copy.not.found", args:[basedir])
+
+    // Use svnkit to get the base revision.
+    def clientManager = SVNClientManager.newInstance()
+    def wcClient = clientManager.getWCClient()
+    try {
+        result.revision = wcClient.doInfo(wc, SVNRevision.BASE).getRevision().toString()
+    }
+    catch(org.tmatesoft.svn.core.SVNException e) {
+        fail(code:"vcs.exception", args:[e])
+    }
+
+    // Success.
+    return result
+} // getVcsRevision()
+
+/** 
+* Update the in memory metadata if already loaded.
+* Available vars: binding.variables.each { println it.key }
+*/
+def updateInMemoryMetadata(revision) {
+    if(binding.variables.containsKey('metadata')) {
+        def metadata = binding.variables['metadata']
+        metadata['app.vcsRevision'] = '$Rev: '+revision+' $'
+    }
+} // updateInMemoryMetadata()
+
+/**
+* Write revision to properties file.
+* @retuns An error map if any errors.
+*/
+def writePropertiesFileRevision(propertiesFile, revision) {
+    def result = [:]
+
+    def fail = { Map m ->
+        result.error = [ code: m.code, args: m.args ]
+        return result
+    }
+
+    if(!propertiesFile.isFile())
+        return fail(code:"application.properties.file.not.found", args:[propertiesFile.getAbsoluteFile()])
+
+    def revisionString = 'app.vcsRevision=\\$Rev: '+revision+' \\$'
+    println "Updating application.properties file with: ${revisionString}"
+
+    def processFileInplace = { file, Closure processText ->
+        def text = file.text
+        file.write(processText(text))
+    }
+
+    processFileInplace(propertiesFile) { text ->
+        text.replaceAll('app.vcsRevision.*', revisionString)
+    }
+
+    // Success.
+    return result
+
+} // writePropertiesFileRevision()
Index: branches/features/taskProcedureRework/src/groovy/net/kromhouts/HqlBuilder.groovy
===================================================================
--- branches/features/taskProcedureRework/src/groovy/net/kromhouts/HqlBuilder.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/groovy/net/kromhouts/HqlBuilder.groovy	(revision 753)
@@ -0,0 +1,482 @@
+/* Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.kromhouts
+
+/**
+ * Provides a DSL for building and managing HQL strings.
+ * For more usage examples see the HqlBuilderTests.
+ * HQL reference see http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/queryhql.html
+ *
+ * DML reference see http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/batch.html#batch-direct
+ * DML-style clauses: "update, delete, insert into" may not be well tested, the "set" clause has basic implementation.
+ * So double check the q.query output for these cases.
+ *
+ * Primary goals:
+ * 1. Easy to read and understand in code.
+ * 2. Easy to read and understand when printed (e.g when displayed in a report).
+ * 3. Easy to execute with correct paginateParams and namedParams.
+ * 4. Easy to change a clause and execute again.
+ *
+ * Basic usage:
+ *    def q = new HqlBuilder().query {
+ *        select 'count(distinct book)'
+ *        from 'Book as book'
+ *        where 'book.id > 100'
+ *            and 'book.inStock = true'
+ *    }
+ *    def totalCount = Book.executeQuery(q.query, q.namedParams, q.paginateParams)[0].toInteger()
+ *    q.select = 'distinct book'
+ *    def list = Book.executeQuery(q.query, q.namedParams, q.paginateParams)
+ *
+ *    def bookList = new PagedResultList(list, totalCount)
+ *    log.debug '\n' + q.printFormattedQuery
+ *
+ * @author Gavin Kromhout
+ * @version DraftB
+ *
+ */
+class HqlBuilder {
+
+    // HQL clauses.
+    // Each clause is a map key with a list of terms.
+    def clauses = [:]
+
+    // HQL namedParams.
+    // HQL requires the namedParams to match exactly with the clause expressions.
+    def namedParams = [:]
+
+    // HQL paginateParams.
+    def paginateParams = [max: 1000, offset: 0]
+
+    // The where clause terms are handled separately from other clauses
+    // and are a list of logicalTerms.
+    // The where clause is built by buildWhereClause.
+    def whereClauseTerms = []
+
+    // LogicalIndexStack holds indexes of the current whereClauseTerm nesting.
+    def logicalIndexStack = []
+
+   def logicalBuilders = [AND: 'and',
+                                        OR: 'or']
+
+    def nestingStack = []
+
+    // Sort and Order.
+    // It is easier and more flexible to simply add order as a clause, e.g: order 'by name desc, id asc'
+    // def sort = "" // e.g. instanceName.id
+    // def order = "" // e.g. asc or desc
+
+    /**
+     * Constructor.
+     * Any property that exists (or responds) in the class may be supplied as an argument.
+     * E.g: max:20, offset:10, debug:true
+     * The debug property does not really exist, but if true and no external log property
+     * has been setup then the internal mockLogger will be configured in debug mode.
+     *
+     * @param args A map of arguments, defaults to an empty map.
+     *
+     */
+    def HqlBuilder(Map args = [:]) {
+        args.each { arg ->
+            def argKey = arg.key.toLowerCase()
+            if(super.hasProperty(argKey))
+                this[argKey] = arg.value
+        }
+        if(!super.metaClass.hasMetaProperty('log'))
+            mockLogging(args.debug)
+        log.debug "HqlBuilder()"
+    }
+
+    /**
+     * Call with no args.
+     *  Has no real use other than to prevent obscure errors.
+     */
+    def call() {
+        log.debug "call()"
+    }
+
+    /**
+     * Call with closure as last arg.
+     * A typically used build call, e.g: q { } is equivalent to q.call() { }
+     */
+    def call(Closure cl) {
+        log.debug "call(Closure cl)"
+        handleClosure(cl)
+    }
+
+    /**
+     * Domain specific build method.
+     *  Has no real use other than to prevent obscure errors
+     * when user makes a call to query() and Groovy calls query(Closure cl)
+     *
+     * @returns This object.
+     *
+     */
+    def query() {
+        log.debug "query()"
+        return this // Must return this object to q.
+    }
+
+    /**
+     * Domain specific build method.
+     * The recommended build call, e.g: def q = new HqlBuilder().query { }
+     *
+     * @param cl The closure that will be used to build the query.
+     * @returns This object.
+     *
+     */
+    def query(Closure cl) {
+        log.debug "query(Closure cl)"
+        handleClosure(cl)
+        return this // Must return this object to q.
+    }
+
+    /**
+     * InvokeMethod resolves all undefined methods.
+     * Which include the clause methods, e.g: select 'book' is equivalent to select('book').
+     * Note that defined methods will be called directly since this class does not implement GroovyInterceptable.
+     * If class was "HqlBuilder implements GroovyInterceptable" then even println would be intercepted and
+     * several exlusions might be needed. e.g: if(methodName != 'call' && methodName != 'println')
+     */
+    def invokeMethod(String methodName, args) {
+
+        log.debug "invokeMethod(${methodName}, ${args})"
+
+        // Call any closures first, that way the nesting is handled and we just keep a reference.
+        if(args[-1] instanceof Closure) {
+            handleClosure(args[-1], methodName)
+            args = args.minus(args[-1])
+        }
+
+        if(!clauses.containsKey(methodName) && !isLogicalBuilder(methodName))
+            clauses[methodName] = []
+
+        if(args) {
+            if(isWhereClauseBuilder(methodName)) {
+                logicalBuilder(methodName, args)
+                return
+            }
+        }
+
+        for(arg in args) {
+            if(arg instanceof String || arg instanceof GString)
+                clauses[methodName] << arg
+        }
+
+    } // invokeMethod()
+
+    /**
+     * PropertyMissing.
+     * Allows clauses to be added after build, e.g: q.order = 'by book.name asc'
+     * and clauses to be removed, e.g: q.order = null
+     */
+    def propertyMissing(String propertyName, value) {
+        log.debug "propertyMissing(${propertyName}, ${value})"
+
+        if(value == null) {
+            removeClause(propertyName)
+            if(propertyName.toLowerCase() == 'where')
+                whereClauseTerms.clear()
+            return
+        }
+
+        if(!clauses.containsKey(propertyName))
+            clauses[propertyName] = []
+
+        // Occurs when user assigns to where clause, e.g: q.where = 'book.id > 100'
+        if(propertyName.toLowerCase() == 'where') {
+            whereClauseTerms.clear()
+            logicalBuilder(propertyName, [value])
+            return
+        }
+
+        if(value instanceof String || value instanceof GString)
+            clauses[propertyName] = [value]
+    } // propertyMissing(String propertyName, value)
+
+    /**
+     * PropertyMissing.
+     * Allow clauses to be accessed directly by name, e.g: println q.order.
+     * Since clauses is a Map null is simply returned for a non-existant clause.
+     */
+    def propertyMissing(String propertyName) {
+        log.debug "propertyMissing(${propertyName})"
+
+        if(!clauses.containsKey(propertyName))
+            clauses[propertyName] = []
+
+        // Occurs when user performs an operation on where clause.
+        // E.g: q.where << "book.id = 100" which is actually NOT a supported operation since
+        // calling the method provides the correct function e.g: q.where "book.id > 100".
+        // Also allows `println q.where` to be short hand for `println q.whereClauseTerms`
+        if(propertyName.toLowerCase() == 'where') {
+            return whereClauseTerms
+        }
+
+        clauses[propertyName]
+    } // propertyMissing(String propertyName)
+
+    def setMax(Integer value) {
+        paginateParams.max = value
+    }
+
+    def getMax() {
+        paginateParams.max
+    }
+
+    def setOffset(Integer value) {
+        paginateParams.offset = value
+    }
+
+    def getOffset() {
+        paginateParams.offset
+    }
+
+    /**
+     * RemoveClause.
+     * Allows clauses to be removed, e.g: q.removeClause('order')
+     *
+     * @param clauseName The clause to remove.
+     *
+     */
+    def removeClause(String clauseName) {
+            clauses.remove(clauseName)
+    }
+
+    /**
+     * BuildWhereClause.
+     * Build the where clause from whereClauseTerms.
+     */
+    def buildWhereClause(printFormat = false) {
+        //log.debug "buildWhereClause()"
+
+        if(!whereClauseTerms)
+            return ''
+
+        def whereClause = 'where '
+
+        def buildExpression // declared separately to allow recurrsion.
+        buildExpression = { term ->
+            def result = ''
+            def termCount = term.expressions.size()
+            if(termCount > 1) {
+                term.expressions.eachWithIndex { t, index ->
+                    if(index == 0)
+                        result += buildExpression(t)
+                    else if(printFormat)
+                        result += " \n\t${t.logic} ${buildExpression(t)}"
+                    else
+                        result += " ${t.logic} ${buildExpression(t)}"
+
+                }
+                result = "( "+result+" )"
+            }
+            else {
+                if(term.expressions[0] instanceof Map)
+                    result += "${term.expressions[0].expressions[0]}"
+                else
+                    result += "${term.expressions[0]}"
+            }
+            return result
+        }
+
+        whereClauseTerms.eachWithIndex { tm, index ->
+            if(index == 0)
+                whereClause += buildExpression(tm)
+            else if(printFormat)
+                whereClause += " \n\t${tm.logic} ${buildExpression(tm)}"
+            else
+                whereClause += " ${tm.logic} ${buildExpression(tm)}"
+        }
+
+        return whereClause
+    } // buildWhereClause(printFormat = false)
+
+    /**
+     * LogicalBuilder.
+     * Build the whereClauseTerms
+     * by appending logicalTerms to the appropriate expressions.
+     */
+    def logicalBuilder(logicalName, args) {
+        log.debug "logicalBuilder(${logicalName}, ${args})"
+        log.debug "logicalIndexStack: ${logicalIndexStack}"
+
+        def logic = getLogicalString(logicalName)
+
+        for(arg in args) {
+            if(arg instanceof String || arg instanceof GString) {
+                arg = arg.trim()
+                if(arg) { // prevent empty strings being added.
+                    if(logicalIndexStack.size() > 0) {
+                        // Append to current index position.
+                        whereClauseTerms[logicalIndexStack[-1]].expressions << logicalTerm(logic, arg)
+                    }
+                    else {
+                        // Append to 'root'.
+                        whereClauseTerms << logicalTerm(logic, null) // empty expression logicalTerm.
+                        whereClauseTerms[-1].expressions << logicalTerm(logic, arg) // append logicalTerm to expressions
+                    }
+                } // if(arg)
+            } // if(arg instanceof)
+        } // for
+
+    } // logicalBuilder(logicalName, args)
+
+    /**
+     * LogicalTerm.
+     * A logicalTerm is a map object that holds the logic and list of expressions of a whereClauseTerm.
+     */
+    def logicalTerm = { logic, expression ->
+        expression = expression ? [expression] : []
+        ['logic': getLogicalString(logic), 'expressions': expression]
+    }
+
+    /**
+     * GetLogicalString.
+     *
+     * @param logicalName The name to get the matching logicalBuilder string for.
+     */
+    private getLogicalString(logicalName) {
+
+        switch(logicalName.toLowerCase()) {
+            case 'where':
+                logicalBuilders.AND
+                break
+            case logicalBuilders.AND:
+                logicalBuilders.AND
+                break
+            case logicalBuilders.OR:
+                logicalBuilders.OR
+                break
+        }
+
+    }
+
+    /**
+     * HandleClosure.
+     * Setting delegate and DELEGATE_FIRST allows closure to access this object's properties first.
+     */
+    private handleClosure(Closure cl, String methodName = 'root') {
+        log.debug "handleClosure(${cl.toString()}, ${methodName})"
+        if(isWhereClauseBuilder(methodName)) {
+            whereClauseTerms << logicalTerm(getLogicalString(methodName), null)
+            logicalIndexStack << whereClauseTerms.size()-1
+        }
+        nestingStack.push(methodName)
+        cl.delegate = this
+        cl.resolveStrategy = Closure.DELEGATE_FIRST
+        cl.call()
+        //log.debug "nestingStack: $nestingStack"
+        nestingStack.pop()
+        if(isWhereClauseBuilder(methodName)) {
+            logicalIndexStack.pop()
+        }
+    }
+
+    /**
+     * MockLogging.
+     * This class has super cow powers and can mock out it's own debug logging.
+     */
+    private mockLogging(debug = false) {
+        def mockLogger = {}
+        if(debug) {
+            mockLogger = {msg ->
+                    println "${super.getClass()} - DEBUG: $msg"
+            }
+        }
+        super.metaClass.log = [debug: mockLogger]
+        log.debug "Internal mockLogger configured."
+    }
+
+    /**
+     * IsLogicalBuilder.
+     * Determine if a method is a logicalBuilder.
+     */
+    private isLogicalBuilder(String methodName) {
+        logicalBuilders.find{ it.value == methodName.toLowerCase()} ? true:false
+    }
+
+    /**
+     * IsWhereClauseBuilder.
+     * Determine if a method is a where clause builder.
+     */
+    private isWhereClauseBuilder(String methodName) {
+        methodName = methodName.toLowerCase()
+        if(methodName == 'where' || isLogicalBuilder(methodName))
+            return true
+        else
+            return false
+    }
+
+    /**
+     * GetQuery.
+     * Assemble and return the query in a format that can be directly executed.
+     * E.g: executeQuery(q.query, q.namedParams, q.paginateParams).
+     */
+    def getQuery() {
+        clauses.collect { clause ->
+            switch (clause.key.toLowerCase()) {
+                case 'select':
+                    clause.key + ' ' + clause.value.join(', ')
+                    break
+                case 'set':
+                    clause.key + ' ' + clause.value.join(', ')
+                    break
+                case 'where':
+                    buildWhereClause()
+                    break
+                case 'order':
+                    clause.key + ' ' + clause.value.join(', ')
+                    break
+                case 'group':
+                    clause.key + ' ' + clause.value.join(', ')
+                    break
+                default:
+                    clause.key + ' ' + clause.value.join(' ')
+            }
+        }.join(' ')
+    } // getQuery()
+
+    /**
+     * GetPrintFormattedQuery.
+     * Assemble and return the query in a format that can be more easily printed and read by a person.
+     * E.g: println q.printFormattedQuery or when displayed in a report.
+     */
+    def getPrintFormattedQuery() {
+        clauses.collect { clause ->
+            switch (clause.key.toLowerCase()) {
+                case 'select':
+                    clause.key + ' ' + clause.value.join(', \n\t')
+                    break
+                case 'set':
+                    clause.key + ' ' + clause.value.join(', \n\t')
+                    break
+                case 'where':
+                    buildWhereClause(true)
+                    break
+                case 'order':
+                    clause.key + ' ' + clause.value.join(', \n\t')
+                    break
+                case 'group':
+                    clause.key + ' ' + clause.value.join(', \n\t')
+                    break
+                default:
+                    clause.key + ' ' + clause.value.join(' \n\t')
+            }
+        }.join(' \n')
+    } // getPrintFormattedQuery()
+
+} // end class
Index: branches/features/taskProcedureRework/src/groovy/org/gnumims/RichUiCalendarItem.groovy
===================================================================
--- branches/features/taskProcedureRework/src/groovy/org/gnumims/RichUiCalendarItem.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/groovy/org/gnumims/RichUiCalendarItem.groovy	(revision 753)
@@ -0,0 +1,13 @@
+package org.gnumims
+
+class RichUiCalendarItem {
+
+    Long id = 0
+    String text = ''
+    Date date = new Date()
+
+    String toString() {
+        "${this.text}"
+    }
+
+}
Index: branches/features/taskProcedureRework/src/templates/artifacts/Controller.groovy
===================================================================
--- branches/features/taskProcedureRework/src/templates/artifacts/Controller.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/artifacts/Controller.groovy	(revision 753)
@@ -0,0 +1,4 @@
+@artifact.package@class @artifact.name@ {
+
+    def index = { }
+}
Index: branches/features/taskProcedureRework/src/templates/artifacts/DomainClass.groovy
===================================================================
--- branches/features/taskProcedureRework/src/templates/artifacts/DomainClass.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/artifacts/DomainClass.groovy	(revision 753)
@@ -0,0 +1,5 @@
+@artifact.package@class @artifact.name@ {
+
+    static constraints = {
+    }
+}
Index: branches/features/taskProcedureRework/src/templates/artifacts/Filters.groovy
===================================================================
--- branches/features/taskProcedureRework/src/templates/artifacts/Filters.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/artifacts/Filters.groovy	(revision 753)
@@ -0,0 +1,17 @@
+@artifact.package@class @artifact.name@ {
+
+    def filters = {
+        all(controller:'*', action:'*') {
+            before = {
+                
+            }
+            after = {
+                
+            }
+            afterView = {
+                
+            }
+        }
+    }
+    
+}
Index: branches/features/taskProcedureRework/src/templates/artifacts/Script.groovy
===================================================================
--- branches/features/taskProcedureRework/src/templates/artifacts/Script.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/artifacts/Script.groovy	(revision 753)
@@ -0,0 +1,7 @@
+includeTargets << grailsScript("Init")
+
+target(main: "The description of the script goes here!") {
+    // TODO: Implement script here
+}
+
+setDefaultTarget(main)
Index: branches/features/taskProcedureRework/src/templates/artifacts/Service.groovy
===================================================================
--- branches/features/taskProcedureRework/src/templates/artifacts/Service.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/artifacts/Service.groovy	(revision 753)
@@ -0,0 +1,8 @@
+@artifact.package@class @artifact.name@ {
+
+    boolean transactional = true
+
+    def serviceMethod() {
+
+    }
+}
Index: branches/features/taskProcedureRework/src/templates/artifacts/TagLib.groovy
===================================================================
--- branches/features/taskProcedureRework/src/templates/artifacts/TagLib.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/artifacts/TagLib.groovy	(revision 753)
@@ -0,0 +1,3 @@
+@artifact.package@class @artifact.name@ {
+
+}
Index: branches/features/taskProcedureRework/src/templates/artifacts/Tests.groovy
===================================================================
--- branches/features/taskProcedureRework/src/templates/artifacts/Tests.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/artifacts/Tests.groovy	(revision 753)
@@ -0,0 +1,15 @@
+@artifact.package@import grails.test.*
+
+class @artifact.name@ extends @artifact.superclass@ {
+    protected void setUp() {
+        super.setUp()
+    }
+
+    protected void tearDown() {
+        super.tearDown()
+    }
+
+    void testSomething() {
+
+    }
+}
Index: branches/features/taskProcedureRework/src/templates/artifacts/WebTest.groovy
===================================================================
--- branches/features/taskProcedureRework/src/templates/artifacts/WebTest.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/artifacts/WebTest.groovy	(revision 753)
@@ -0,0 +1,54 @@
+class @webtest.name.caps@Test extends grails.util.WebTest {
+
+    // Unlike unit tests, functional tests are often sequence dependent.
+    // Specify that sequence here.
+    void suite() {
+        test@webtest.name.caps@ListNewDelete()
+        // add tests for more operations here
+    }
+
+    def test@webtest.name.caps@ListNewDelete() {
+        webtest('@webtest.name.caps@ basic operations: view list, create new entry, view, edit, delete, view') {
+            invoke(url:'@webtest.name.lower@')
+            verifyText(text:'Home')
+
+            verifyListPage(0)
+
+            clickLink(label:'New @webtest.name.caps@')
+            verifyText(text:'Create @webtest.name.caps@')
+            clickButton(label:'Create')
+            verifyText(text:'Show @webtest.name.caps@', description:'Detail page')
+            clickLink(label:'List', description:'Back to list view')
+
+            verifyListPage(1)
+
+            group(description:'edit the one element') {
+                clickLink(label:'Show', description:'go to detail view')
+                clickButton(label:'Edit')
+                verifyText(text:'Edit @webtest.name.caps@')
+                clickButton(label:'Update')
+                verifyText(text:'Show @webtest.name.caps@')
+                clickLink(label:'List', description:'Back to list view')
+            }
+
+            verifyListPage(1)
+
+            group(description:'delete the only element') {
+                clickLink(label:'Show', description:'go to detail view')
+                clickButton(label:'Delete')
+                verifyXPath(xpath:"//div[@class='message']", text:/@webtest.name.caps@.*deleted./, regex:true)
+            }
+
+            verifyListPage(0)
+        }
+    }
+
+    String ROW_COUNT_XPATH = "count(//td[@class='actionButtons']/..)"
+
+    def verifyListPage(int count) {
+        ant.group(description:"verify @webtest.name.caps@ list view with $count row(s)") {
+            verifyText(text:'@webtest.name.caps@ List')
+            verifyXPath(xpath:ROW_COUNT_XPATH, text:count, description:"$count row(s) of data expected")
+        }
+    }
+}
Index: branches/features/taskProcedureRework/src/templates/scaffolding/Controller.groovy
===================================================================
--- branches/features/taskProcedureRework/src/templates/scaffolding/Controller.groovy	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/scaffolding/Controller.groovy	(revision 753)
@@ -0,0 +1,99 @@
+import org.codehaus.groovy.grails.plugins.springsecurity.Secured
+
+<%=packageName ? "package ${packageName}\n\n" : ''%>class ${className}Controller extends BaseAppAdminController {
+    
+    def index = { redirect(action:list,params:params) }
+
+    // the delete, save and update actions only accept POST requests
+    static allowedMethods = [delete:'POST', save:'POST', update:'POST']
+
+    def list = {
+        params.max = Math.min( params.max ? params.max.toInteger() : 10,  100)
+        [ ${propertyName}List: ${className}.list( params ), ${propertyName}Total: ${className}.count() ]
+    }
+
+    def show = {
+        def ${propertyName} = ${className}.get( params.id )
+
+        if(!${propertyName}) {
+            flash.message = "${className} not found with id \${params.id}"
+            redirect(action:list)
+        }
+        else { return [ ${propertyName} : ${propertyName} ] }
+    }
+
+    def delete = {
+        def ${propertyName} = ${className}.get( params.id )
+        if(${propertyName}) {
+            try {
+                ${propertyName}.delete(flush:true)
+                flash.message = "${className} \${params.id} deleted"
+                redirect(action:list)
+            }
+            catch(org.springframework.dao.DataIntegrityViolationException e) {
+                flash.message = "${className} \${params.id} could not be deleted"
+                redirect(action:show,id:params.id)
+            }
+        }
+        else {
+            flash.message = "${className} not found with id \${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def edit = {
+        def ${propertyName} = ${className}.get( params.id )
+
+        if(!${propertyName}) {
+            flash.message = "${className} not found with id \${params.id}"
+            redirect(action:list)
+        }
+        else {
+            return [ ${propertyName} : ${propertyName} ]
+        }
+    }
+
+    def update = {
+        def ${propertyName} = ${className}.get( params.id )
+        if(${propertyName}) {
+            if(params.version) {
+                def version = params.version.toLong()
+                if(${propertyName}.version > version) {
+                    <%def lowerCaseName = grails.util.GrailsNameUtils.getPropertyName(className)%>
+                    ${propertyName}.errors.rejectValue("version", "default.optimistic.locking.failure")
+                    render(view:'edit',model:[${propertyName}:${propertyName}])
+                    return
+                }
+            }
+            ${propertyName}.properties = params
+            if(!${propertyName}.hasErrors() && ${propertyName}.save(flush: true)) {
+                flash.message = "${className} \${params.id} updated"
+                redirect(action:show,id:${propertyName}.id)
+            }
+            else {
+                render(view:'edit',model:[${propertyName}:${propertyName}])
+            }
+        }
+        else {
+            flash.message = "${className} not found with id \${params.id}"
+            redirect(action:list)
+        }
+    }
+
+    def create = {
+        def ${propertyName} = new ${className}()
+        ${propertyName}.properties = params
+        return ['${propertyName}':${propertyName}]
+    }
+
+    def save = {
+        def ${propertyName} = new ${className}(params)
+        if(!${propertyName}.hasErrors() && ${propertyName}.save(flush: true)) {
+            flash.message = "${className} \${${propertyName}.id} created"
+            redirect(action:show,id:${propertyName}.id)
+        }
+        else {
+            render(view:'create',model:[${propertyName}:${propertyName}])
+        }
+    }
+}
Index: branches/features/taskProcedureRework/src/templates/scaffolding/create.gsp
===================================================================
--- branches/features/taskProcedureRework/src/templates/scaffolding/create.gsp	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/scaffolding/create.gsp	(revision 753)
@@ -0,0 +1,59 @@
+<% import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor as Events %>
+<%=packageName%>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Create ${className}</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">${className} List</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Create ${className}</h1>
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="\${${propertyName}}">
+            <div class="errors">
+                <g:renderErrors bean="\${${propertyName}}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form action="save" method="post" <%= multiPart ? ' enctype="multipart/form-data"' : '' %>>
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        <%
+
+                            excludedProps = ['version',
+                                             'id',
+                                               Events.ONLOAD_EVENT,
+                                               Events.BEFORE_DELETE_EVENT,
+                                               Events.BEFORE_INSERT_EVENT,
+                                               Events.BEFORE_UPDATE_EVENT]
+                            props = domainClass.properties.findAll { !excludedProps.contains(it.name) }
+
+                            Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
+                            props.each { p ->
+                                if(!Collection.class.isAssignableFrom(p.type)) {
+                                    cp = domainClass.constrainedProperties[p.name]
+                                    display = (cp ? cp.display : true)        
+                                    if(display) { %>
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="${p.name}">${p.naturalName}:</label>
+                                </td>
+                                <td valign="top" class="value \${hasErrors(bean:${propertyName},field:'${p.name}','errors')}">
+                                    ${renderEditor(p)}
+                                </td>
+                            </tr> 
+                        <%  }   }   } %>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><input class="save" type="submit" value="Create" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/src/templates/scaffolding/edit.gsp
===================================================================
--- branches/features/taskProcedureRework/src/templates/scaffolding/edit.gsp	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/scaffolding/edit.gsp	(revision 753)
@@ -0,0 +1,62 @@
+<% import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor as Events %>
+<%=packageName%>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Edit ${className}</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">${className} List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New ${className}</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Edit ${className}</h1>
+            <g:render template="/shared/messages" />
+            <g:hasErrors bean="\${${propertyName}}">
+            <div class="errors">
+                <g:renderErrors bean="\${${propertyName}}" as="list" />
+            </div>
+            </g:hasErrors>
+            <g:form method="post" <%= multiPart ? ' enctype="multipart/form-data"' : '' %>>
+                <input type="hidden" name="id" value="\${${propertyName}?.id}" />
+                <input type="hidden" name="version" value="\${${propertyName}?.version}" />
+                <div class="dialog">
+                    <table>
+                        <tbody>
+                        <%
+                            excludedProps = ['version',
+                                             'id',
+                                               Events.ONLOAD_EVENT,
+                                               Events.BEFORE_DELETE_EVENT,
+                                               Events.BEFORE_INSERT_EVENT,
+                                               Events.BEFORE_UPDATE_EVENT]
+                            props = domainClass.properties.findAll { !excludedProps.contains(it.name) }
+                            
+                            Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
+                            props.each { p ->
+                                cp = domainClass.constrainedProperties[p.name]
+                                display = (cp ? cp.display : true)        
+                                if(display) { %>
+                            <tr class="prop">
+                                <td valign="top" class="name">
+                                    <label for="${p.name}">${p.naturalName}:</label>
+                                </td>
+                                <td valign="top" class="value \${hasErrors(bean:${propertyName},field:'${p.name}','errors')}">
+                                    ${renderEditor(p)}
+                                </td>
+                            </tr> 
+                        <%  }   } %>
+                        </tbody>
+                    </table>
+                </div>
+                <div class="buttons">
+                    <span class="button"><g:actionSubmit class="save" value="Update" /></span>
+                    <span class="button"><g:actionSubmit class="cancel" value="Cancel" action="Show"/></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </div>
+            </g:form>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/src/templates/scaffolding/list.gsp
===================================================================
--- branches/features/taskProcedureRework/src/templates/scaffolding/list.gsp	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/scaffolding/list.gsp	(revision 753)
@@ -0,0 +1,57 @@
+<% import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor as Events %>
+<%=packageName%>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>${className} List</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="create" action="create">New ${className}</g:link></span>
+        </div>
+        <div class="body">
+            <h1>${className} List</h1>
+            <g:render template="/shared/messages" />
+            <div class="list">
+                <table>
+                    <thead>
+                        <tr>
+                        <%
+                            excludedProps = ['version',
+                                               Events.ONLOAD_EVENT,
+                                               Events.BEFORE_DELETE_EVENT,
+                                               Events.BEFORE_INSERT_EVENT,
+                                               Events.BEFORE_UPDATE_EVENT]
+                            
+                            props = domainClass.properties.findAll { !excludedProps.contains(it.name) && it.type != Set.class }
+                            Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
+                            props.eachWithIndex { p,i ->
+                   	            if(i < 6) {
+                   	                if(p.isAssociation()) { %>
+                   	        <th>${p.naturalName}</th>
+                   	    <%          } else { %>
+                   	        <g:sortableColumn property="${p.name}" title="${p.naturalName}" />
+                        <%  }   }   } %>
+                        </tr>
+                    </thead>
+                    <tbody>
+                    <g:each in="\${${propertyName}List}" status="i" var="${propertyName}">
+                        <tr class="\${(i % 2) == 0 ? 'odd' : 'even'}">
+                        <%  props.eachWithIndex { p,i ->
+                                if(i == 0) { %>
+                            <td><g:link action="show" id="\${${propertyName}.id}">\${fieldValue(bean:${propertyName}, field:'${p.name}')}</g:link></td>
+                        <%      } else if(i < 6) { %>
+                            <td>\${fieldValue(bean:${propertyName}, field:'${p.name}')}</td>
+                        <%  }   } %>
+                        </tr>
+                    </g:each>
+                    </tbody>
+                </table>
+            </div>
+            <div class="paginateButtons">
+                <g:paginate total="\${${propertyName}Total}" />
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/src/templates/scaffolding/renderEditor.template
===================================================================
--- branches/features/taskProcedureRework/src/templates/scaffolding/renderEditor.template	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/scaffolding/renderEditor.template	(revision 753)
@@ -0,0 +1,190 @@
+<%  if(property.type == Boolean.class || property.type == boolean.class)
+        out << renderBooleanEditor(domainClass,property)	
+    else if(Number.class.isAssignableFrom(property.type) || (property.type.isPrimitive() && property.type != boolean.class))
+        out << renderNumberEditor(domainClass,property)
+    else if(property.type == String.class)
+        out << renderStringEditor(domainClass,property)
+    else if(property.type == Date.class || property.type == java.sql.Date.class || property.type == java.sql.Time.class)
+        out << renderDateEditor(domainClass,property)
+    else if(property.type == Calendar.class)
+        out << renderDateEditor(domainClass,property)  
+    else if(property.type == URL.class) 
+        out << renderStringEditor(domainClass,property)
+    else if(property.isEnum())
+        out << renderEnumEditor(domainClass,property)
+    else if(property.type == TimeZone.class)
+        out << renderSelectTypeEditor("timeZone",domainClass,property)
+    else if(property.type == Locale.class)
+        out << renderSelectTypeEditor("locale",domainClass,property)
+    else if(property.type == Currency.class)
+        out << renderSelectTypeEditor("currency",domainClass,property)
+    else if(property.type==([] as Byte[]).class) //TODO: Bug in groovy means i have to do this :(
+        out << renderByteArrayEditor(domainClass,property)
+    else if(property.type==([] as byte[]).class) //TODO: Bug in groovy means i have to do this :(
+        out << renderByteArrayEditor(domainClass,property)                
+    else if(property.manyToOne || property.oneToOne)
+        out << renderManyToOne(domainClass,property)
+    else if((property.oneToMany && !property.bidirectional) || (property.manyToMany && property.isOwningSide()))
+        out << renderManyToMany(domainClass, property)
+    else if(property.oneToMany)
+        out << renderOneToMany(domainClass,property)
+
+    private renderEnumEditor(domainClass,property) {
+        if(property.isEnum()) {
+            return "<g:select  from=\"\${${property.type.name}?.values()}\" value=\"\${${domainInstance}?.${property.name}}\" name=\"${property.name}\" ${renderNoSelection(property)}></g:select>"
+        }
+    }
+
+    private renderStringEditor(domainClass, property) {
+        if(!cp) {
+            return "<input type=\"text\" name=\"${property.name}\" id=\"${property.name}\" value=\"\${fieldValue(bean:${domainInstance},field:'${property.name}')}\" />"
+        }
+        else {
+            if("textarea" == cp.widget || (cp.maxSize > 250 && !cp.password && !cp.inList)) {
+                return "<textarea rows=\"5\" cols=\"40\" name=\"${property.name}\">\${fieldValue(bean:${domainInstance}, field:'${property.name}')}</textarea>"
+            }
+             else {
+                if(cp.inList) {
+                    def sb = new StringBuffer('<g:select ')
+                    sb << "id=\"${property.name}\" name=\"${property.name}\" from=\"\${${domainInstance}.constraints.${property.name}.inList}\" value=\"\${${domainInstance}.${property?.name}}\" ${renderNoSelection(property)}>"
+                    sb << '</g:select>'
+                    return sb.toString()
+                }
+                else {
+                    def sb = new StringBuffer('<input ')
+                    cp.password ? sb << 'type="password" ' : sb << 'type="text" '
+                    if(!cp.editable) sb << 'readonly="readonly" '
+                    if(cp.maxSize) sb << "maxlength=\"${cp.maxSize}\" "
+                    sb << "id=\"${property.name}\" name=\"${property.name}\" value=\"\${fieldValue(bean:${domainInstance},field:'${property.name}')}\"/>"
+                    return sb.toString()
+                }
+            }
+        }
+    }
+
+    private renderByteArrayEditor(domainClass,property) {
+        return "<input type=\"file\" id=\"${property.name}\" name=\"${property.name}\" />"
+    }
+
+    private renderManyToOne(domainClass,property) {
+        if(property.association) {
+            return "<g:select optionKey=\"id\" from=\"\${${property.type.name}.list()}\" name=\"${property.name}.id\" value=\"\${${domainInstance}?.${property.name}?.id}\" ${renderNoSelection(property)}></g:select>"
+        }
+    }
+
+    private renderManyToMany(domainClass,property) {
+        def sw = new StringWriter()
+        def pw = new PrintWriter(sw)
+
+        pw.println "<g:select name=\"${property.name}\""
+        pw.println "from=\"\${${property.referencedDomainClass.fullName}.list()}\""
+        pw.println "size=\"5\" multiple=\"yes\" optionKey=\"id\""
+        pw.println "value=\"\${${domainInstance}?.${property.name}}\" />"
+
+        return sw.toString()         
+    }
+
+    private renderOneToMany(domainClass,property) {
+        def sw = new StringWriter()
+        def pw = new PrintWriter(sw)
+        pw.println()
+        pw.println "<ul>"
+        pw.println "<g:each var=\"${property.name[0]}\" in=\"\${${domainInstance}?.${property.name}?}\">"
+        pw.println "    <li><g:link controller=\"${property.referencedDomainClass.propertyName}\" action=\"show\" id=\"\${${property.name[0]}.id}\">\${${property.name[0]}?.encodeAsHTML()}</g:link></li>"
+        pw.println "</g:each>"
+        pw.println "</ul>"
+        pw.println "<g:link controller=\"${property.referencedDomainClass.propertyName}\" params=\"['${domainClass.propertyName}.id':${domainInstance}?.id]\" action=\"create\">+Add ${property.referencedDomainClass.shortName}</g:link>"
+        return sw.toString()
+    }
+
+    private renderNumberEditor(domainClass,property) {
+        if(!cp) {
+            if(property.type == Byte.class) {
+                return "<g:select from=\"\${-128..127}\" name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\"></g:select>"
+            }
+            else {
+                return "<input type=\"text\" id=\"${property.name}\" name=\"${property.name}\" value=\"\${fieldValue(bean:${domainInstance},field:'${property.name}')}\" />"
+            }
+        }
+        else {
+            if(cp.range) {
+                return "<g:select from=\"\${${cp.range.from}..${cp.range.to}}\" id=\"${property.name}\" name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\" ${renderNoSelection(property)}></g:select>"
+            }
+            else if(cp.inList) {
+                def sb = new StringBuffer('<g:select ')
+                sb << "id=\"${property.name}\" name=\"${property.name}\" from=\"\${${domainClass.propertyName}.constraints.${property.name}.inList}\" value=\"\${${domainClass.propertyName}.${property?.name}}\" ${renderNoSelection(property)}>"
+                sb << '</g:select>'
+                return sb.toString()
+            }            
+            else {
+                return "<input type=\"text\" id=\"${property.name}\" name=\"${property.name}\" value=\"\${fieldValue(bean:${domainInstance},field:'${property.name}')}\" />"
+            }
+        }
+     }
+
+    private renderBooleanEditor(domainClass,property) {
+        if(!cp) {
+            return "<g:checkBox name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\"></g:checkBox>"
+        }
+        else {
+            def buf = new StringBuffer('<g:checkBox ')
+            if(cp.widget) buf << "widget=\"${cp.widget}\"";
+
+            buf << "name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\" "
+            cp.attributes.each { k,v ->
+                buf << "${k}=\"${v}\" "
+            }
+            buf << '></g:checkBox>'
+            return buf.toString()
+        }
+    }
+
+    private renderDateEditor(domainClass,property) {
+        def precision = property.type == java.sql.Date ? 'day' : 'minute';
+        if(!cp) {
+            return "<g:datePicker name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\" precision=\"${precision}\"></g:datePicker>"
+        }
+        else {
+            if(!cp.editable) {
+                return "\${${domainInstance}?.${property.name}?.toString()}"
+            }
+            else {
+                def buf = new StringBuffer('<g:datePicker ')
+                if(cp.widget) buf << "widget=\"${cp.widget}\" "
+                if(cp.format) buf << "format=\"${cp.format}\" "
+                cp.attributes.each { k,v ->
+                    buf << "${k}=\"${v}\" "
+                }
+                buf << "name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\" precision=\"${precision}\" ${renderNoSelection(property)}></g:datePicker>"
+                return buf.toString()
+            }
+        }
+    }
+
+    private renderSelectTypeEditor(type,domainClass,property) {
+        if(!cp) {
+            return "<g:${type}Select name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\"></g:${type}Select>"
+        }
+        else {
+            def buf = new StringBuffer("<g:${type}Select ")
+            if(cp.widget) buf << "widget=\"${cp.widget}\" ";
+            cp.attributes.each { k,v ->
+                buf << "${k}=\"${v}\" "
+            }
+            buf << "name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\" ${renderNoSelection(property)}></g:${type}Select>"
+            return buf.toString()
+        }
+    }
+
+    private renderNoSelection(property) {
+        if(property.optional) {
+            if(property.manyToOne || property.oneToOne) {
+                return "noSelection=\"['null':'']\""				
+            }
+            else {
+                return "noSelection=\"['':'']\""
+            }
+        }
+        return ""
+    }
+%>
Index: branches/features/taskProcedureRework/src/templates/scaffolding/show.gsp
===================================================================
--- branches/features/taskProcedureRework/src/templates/scaffolding/show.gsp	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/scaffolding/show.gsp	(revision 753)
@@ -0,0 +1,61 @@
+<% import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor as Events %>
+<%=packageName%>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+        <meta name="layout" content="main" />
+        <title>Show ${className}</title>
+    </head>
+    <body>
+        <div class="nav">
+            <span class="menuButton"><g:link class="list" action="list">${className} List</g:link></span>
+            <span class="menuButton"><g:link class="create" action="create">New ${className}</g:link></span>
+        </div>
+        <div class="body">
+            <h1>Show ${className}</h1>
+            <g:render template="/shared/messages" />
+            <div class="dialog">
+                <table>
+                    <tbody>
+
+                    <%
+                        excludedProps = ['version',
+                                           Events.ONLOAD_EVENT,
+                                           Events.BEFORE_DELETE_EVENT,
+                                           Events.BEFORE_INSERT_EVENT,
+                                           Events.BEFORE_UPDATE_EVENT]
+                        props = domainClass.properties.findAll { !excludedProps.contains(it.name) }
+                        Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
+                        props.each { p -> %>
+                        <tr class="prop">
+                            <td valign="top" class="name">${p.naturalName}:</td>
+                            <% if(p.isEnum()) { %>
+                            <td valign="top" class="value">\${${propertyName}?.${p.name}?.encodeAsHTML()}</td>
+                            <% } else if(p.oneToMany || p.manyToMany) { %>
+                            <td  valign="top" style="text-align:left;" class="value">
+                                <ul>
+                                <g:each var="${p.name[0]}" in="\${${propertyName}.${p.name}}">
+                                    <li><g:link controller="${p.referencedDomainClass?.propertyName}" action="show" id="\${${p.name[0]}.id}">\${${p.name[0]}?.encodeAsHTML()}</g:link></li>
+                                </g:each>
+                                </ul>
+                            </td>
+                            <%  } else if(p.manyToOne || p.oneToOne) { %>
+                            <td valign="top" class="value"><g:link controller="${p.referencedDomainClass?.propertyName}" action="show" id="\${${propertyName}?.${p.name}?.id}">\${${propertyName}?.${p.name}?.encodeAsHTML()}</g:link></td>
+                            <%  } else  { %>
+                            <td valign="top" class="value">\${fieldValue(bean:${propertyName}, field:'${p.name}')}</td>
+                            <%  } %>
+                        </tr>
+                    <%  } %>
+                    </tbody>
+                </table>
+            </div>
+            <div class="buttons">
+                <g:form>
+                    <input type="hidden" name="id" value="\${${propertyName}?.id}" />
+                    <span class="button"><g:actionSubmit class="edit" value="Edit" /></span>
+                    <span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
+                </g:form>
+            </div>
+        </div>
+    </body>
+</html>
Index: branches/features/taskProcedureRework/src/templates/war/web.xml
===================================================================
--- branches/features/taskProcedureRework/src/templates/war/web.xml	(revision 753)
+++ branches/features/taskProcedureRework/src/templates/war/web.xml	(revision 753)
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app version="2.4"
+         xmlns="http://java.sun.com/xml/ns/j2ee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+    <display-name>/@grails.project.key@</display-name>
+
+
+    <context-param>
+        <param-name>contextConfigLocation</param-name>
+        <param-value>/WEB-INF/applicationContext.xml</param-value>
+    </context-param>
+
+    <context-param>
+        <param-name>webAppRootKey</param-name>
+        <param-value>@grails.project.key@</param-value>
+    </context-param>
+
+    <filter>
+        <filter-name>sitemesh</filter-name>
+        <filter-class>org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter</filter-class>
+    </filter>
+
+    <filter>
+        <filter-name>charEncodingFilter</filter-name>
+        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
+        <init-param>
+            <param-name>targetBeanName</param-name>
+            <param-value>characterEncodingFilter</param-value>
+        </init-param>
+        <init-param>
+            <param-name>targetFilterLifecycle</param-name>
+            <param-value>true</param-value>
+        </init-param>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>charEncodingFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
+    <filter-mapping>
+        <filter-name>sitemesh</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+
+    <listener>
+        <listener-class>org.codehaus.groovy.grails.web.util.Log4jConfigListener</listener-class>
+    </listener>
+
+    <listener>
+        <listener-class>org.codehaus.groovy.grails.web.context.GrailsContextLoaderListener</listener-class>
+    </listener>
+
+    <!-- Grails dispatcher servlet -->
+    <servlet>
+        <servlet-name>grails</servlet-name>
+        <servlet-class>org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet</servlet-class>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+    <!-- The Groovy Server Pages servlet -->
+    <servlet>
+        <servlet-name>gsp</servlet-name>
+        <servlet-class>org.codehaus.groovy.grails.web.pages.GroovyPagesServlet</servlet-class>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>gsp</servlet-name>
+        <url-pattern>*.gsp</url-pattern>
+    </servlet-mapping>
+
+    <welcome-file-list>
+        <!--
+        The order of the welcome pages is important.  JBoss deployment will
+        break if index.gsp is first in the list.
+        -->
+        <welcome-file>index.html</welcome-file>
+        <welcome-file>index.jsp</welcome-file>
+        <welcome-file>index.gsp</welcome-file>
+    </welcome-file-list>
+
+    <jsp-config>
+        <taglib>
+            <taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
+            <taglib-location>/WEB-INF/tld/c.tld</taglib-location>
+        </taglib>
+        <taglib>
+            <taglib-uri>http://java.sun.com/jsp/jstl/fmt</taglib-uri>
+            <taglib-location>/WEB-INF/tld/fmt.tld</taglib-location>
+        </taglib>
+        <taglib>
+            <taglib-uri>http://www.springframework.org/tags</taglib-uri>
+            <taglib-location>/WEB-INF/tld/spring.tld</taglib-location>
+        </taglib>
+        <taglib>
+            <taglib-uri>http://grails.codehaus.org/tags</taglib-uri>
+            <taglib-location>/WEB-INF/tld/grails.tld</taglib-location>
+        </taglib>
+    </jsp-config>
+
+</web-app>
Index: branches/features/taskProcedureRework/test/integration/CreateDataServiceTests.groovy
===================================================================
--- branches/features/taskProcedureRework/test/integration/CreateDataServiceTests.groovy	(revision 753)
+++ branches/features/taskProcedureRework/test/integration/CreateDataServiceTests.groovy	(revision 753)
@@ -0,0 +1,108 @@
+import grails.test.*
+
+/**
+* Integration tests for CreateDataService.
+*/
+class CreateDataServiceTests extends GroovyTestCase {
+
+    // By default Grails will rollback the transaction after each test.
+    // Other tests may set this to false so be sure to assert-call-assert.
+    boolean transactional = true
+
+    def appConfigService
+    def createDataService
+
+    // Setup is called before each test.
+    protected void setUp() {
+        super.setUp()
+    }
+
+    // Tear down is called after each test.
+    protected void tearDown() {
+        super.tearDown()
+    }
+
+    void testBaseDataCreated() {
+
+        // Base data should have been created during bootstrap.
+        assertTrue appConfigService.exists("baseDataCreated")
+
+        // Some base data has indeed been created.
+        assert PersonGroupType.count() > 0
+
+    } // testBaseDataCreated()
+
+    void testCreateBaseData() {
+
+        // Base data has already been created in bootstrap,
+        // therefore simply running this will create a host of unique constraint errors
+        // if the method does not exit at the correct point and return false.
+        assertFalse createDataService.createBaseData()
+
+    } // testCreateBaseData()
+
+    void testCreateDemoData() {
+
+        def taskCount
+
+        // No demo tasks yet.
+        taskCount = Task.count()
+        assert taskCount == 0
+
+        // Base data has already been created in bootstrap so
+        // demo data creation should go forward.
+        assertTrue createDataService.createDemoData()
+
+        // Should now have some demo tasks.
+        taskCount = Task.count()
+        assert taskCount > 0
+
+        // Returns false since demo data has already been created.
+        assertFalse createDataService.createDemoData()
+
+        // Task count should not have changed.
+        assert Task.count() == taskCount
+
+    } // testCreateDemoData()
+
+    void testDemoDataCreationDisabled() {
+
+        def taskCount
+
+        // No demo tasks yet.
+        taskCount = Task.count()
+        assert taskCount == 0
+
+        appConfigService.set("demoDataCreationDisabled")
+
+        // False since demo data creation has disabled.
+        assertFalse createDataService.createDemoData()
+
+        // Still no demo tasks.
+        taskCount = Task.count()
+        assert taskCount == 0
+
+    } // testDemoDataCreationDisabled()
+
+    void testCreateDemoDataWithNoBaseData() {
+
+        def taskCount
+
+        // No demo tasks yet.
+        taskCount = Task.count()
+        assert taskCount == 0
+
+        // Base data has already been created in bootstrap so
+        // simulate base data not created.
+        assertTrue appConfigService.delete("baseDataCreated")
+
+        // Returns false since demo data creation has not been recorded.
+        assertFalse createDataService.createDemoData()
+
+        // Still no demo tasks.
+        taskCount = Task.count()
+        assert taskCount == 0
+
+    } // testCreateDemoDataWithNoBaseData()
+
+} // end class
Index: branches/features/taskProcedureRework/test/integration/TaskSearchServiceTests.groovy
===================================================================
--- branches/features/taskProcedureRework/test/integration/TaskSearchServiceTests.groovy	(revision 753)
+++ branches/features/taskProcedureRework/test/integration/TaskSearchServiceTests.groovy	(revision 753)
@@ -0,0 +1,219 @@
+import grails.test.*
+
+/**
+* Integration tests for TaskSearchService.
+*/
+class TaskSearchServiceTests extends GroovyTestCase {
+
+    // Data will be saved, not rolled back.
+    // Be sure to clean up in tearDown().
+    boolean transactional = false
+
+    def taskService
+    def dateUtilService
+    def taskSearchService
+    def assignedGroupService
+    def assignedPersonService
+
+    def taskA
+    def taskB
+    def taskCount = 0
+
+    // Setup is called before each test.
+    protected void setUp() {
+        super.setUp()
+
+        // Check environment state.
+        assert Task.count() == 0
+        assert Entry.count() == 0
+        assert TaskModification.count() == 0
+
+        def p = [:]
+        def result
+
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
+                taskPriority:TaskPriority.get(2),
+                taskType:TaskType.get(1),
+                leadPerson:Person.get(1),
+                description:"TestA",
+                comment:"Service test task.",
+                targetStartDate: dateUtilService.today,
+                targetCompletionDate: dateUtilService.today]
+
+        result = taskService.save(p)
+        assert result.error == null
+        taskCount++
+        taskA = result.taskInstance.refresh()
+
+        p.description = "TestB"
+        result = taskService.save(p)
+        assert result.error == null
+        taskCount++
+        taskB = result.taskInstance.refresh()
+    }
+
+    // Tear down is called after each test.
+    protected void tearDown() {
+
+        taskService.delete(taskA)
+        taskService.delete(taskB)
+
+        // Ensure that we leave environment clean.
+        assert Task.count() == 0
+        assert TaskModification.count() == 0
+        assert Entry.count() == 0
+
+        super.tearDown()
+    }
+
+
+    /**
+    * Test GetTasks.
+    */
+    void testGetTasks() {
+        // Todays tasks should be returned.
+        def tasks = taskSearchService.getTasks([:])
+        assert tasks.totalCount == taskCount
+
+        // Tasks in the trash should not be returned.
+        taskA.trash = true
+        taskA.save(flush:true)
+        assert taskSearchService.getTasks([:]).totalCount == taskCount - 1
+        taskB.trash = true
+        taskB.save(flush:true)
+        assert taskSearchService.getTasks([:]).totalCount == taskCount - 2
+
+        // Restored tasks should be returned.
+        taskA.trash = false
+        taskA.save(flush:true)
+        assert taskSearchService.getTasks([:]).totalCount == taskCount - 1
+        taskB.trash = false
+        taskB.save(flush:true)
+        assert taskSearchService.getTasks([:]).totalCount == taskCount
+
+        // Tomorrows tasks should not be returned.
+        taskA.targetStartDate = dateUtilService.tomorrow
+        taskA.targetCompletionDate = dateUtilService.tomorrow
+        taskA.save(flush:true)
+        assert taskSearchService.getTasks([:]).totalCount == taskCount - 1
+
+        // Tomorrows tasks should be returned, if we ask for them.
+        assert taskSearchService.getTasks([:], dateUtilService.today, dateUtilService.tomorrow+1).totalCount == taskCount
+
+        // Yesterdays tasks should not be returned.
+        taskA.targetStartDate = dateUtilService.yesterday
+        taskA.targetCompletionDate = dateUtilService.yesterday
+        taskA.save(flush:true)
+        assert taskSearchService.getTasks([:]).totalCount == taskCount - 1
+
+        // Yesterdays tasks should be returned, if we ask for them.
+        assert taskSearchService.getTasks([:], dateUtilService.yesterday, dateUtilService.tomorrow).totalCount == taskCount
+
+        // Tasks that span today should be returned.
+        taskA.targetStartDate = dateUtilService.yesterday
+        taskA.targetCompletionDate = dateUtilService.tomorrow
+        taskA.save(flush:true)
+        assert taskSearchService.getTasks([:]).totalCount == taskCount
+    } // testGetTasks()
+
+    /**
+    * Test GetPersonsTasks.
+    */
+    void testGetPersonsTasks() {
+
+        def p = [:]
+        def params = [:]
+
+        // Todays tasks should be returned, since Person #1 is lead and created the tasks.
+        def tasks = taskSearchService.getPersonsTasks(params)
+        assert tasks.totalCount == taskCount
+
+        // Tasks in the trash should not be returned.
+        taskA.trash = true
+        taskA.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params).totalCount == taskCount - 1
+        taskB.trash = true
+        taskB.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params).totalCount == taskCount - 2
+
+        // Restored tasks should be returned.
+        taskA.trash = false
+        taskA.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params).totalCount == taskCount - 1
+        taskB.trash = false
+        taskB.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params).totalCount == taskCount
+
+        // Tomorrows tasks should not be returned.
+        taskA.targetStartDate = dateUtilService.tomorrow
+        taskA.targetCompletionDate = dateUtilService.tomorrow
+        taskA.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params).totalCount == taskCount - 1
+
+        // Tomorrows tasks should be returned, if we ask for them.
+        assert taskSearchService.getPersonsTasks(params, null, dateUtilService.today, dateUtilService.tomorrow+1).totalCount == taskCount
+
+        // Yesterdays tasks should not be returned.
+        taskA.targetStartDate = dateUtilService.yesterday
+        taskA.targetCompletionDate = dateUtilService.yesterday
+        taskA.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params).totalCount == taskCount - 1
+
+        // Yesterdays tasks should be returned, if we ask for them.
+        assert taskSearchService.getPersonsTasks(params, null, dateUtilService.yesterday, dateUtilService.tomorrow).totalCount == taskCount
+
+        // Tasks that span today should be returned.
+        taskA.targetStartDate = dateUtilService.yesterday
+        taskA.targetCompletionDate = dateUtilService.tomorrow
+        taskA.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params).totalCount == taskCount
+
+        // Tasks for a different person should not be returned.
+        taskA.leadPerson = Person.get(2)
+        taskA.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params).totalCount == taskCount - 1
+
+        // Tasks for a specified leadPerson should be returned.
+        // But only if approved since this person did not create the tasks.
+        taskA.leadPerson = Person.get(2)
+        taskA.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params, Person.get(2)).totalCount == 0
+        taskA.approved = true
+        taskA.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params, Person.get(2)).totalCount == 1
+        // Moving the task to the trash, stops it being returned.
+        taskA.trash = true
+        taskA.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params, Person.get(2)).totalCount == 0
+
+        // Tasks assigned to a person should be returned.
+        // But only if approved.
+        p = [person: Person.get(2),
+                task: taskB,
+                estimatedHour: 1,
+                estimatedMinute: 20]
+        assert assignedPersonService.save(p).error == null
+        assert taskSearchService.getPersonsTasks(params, Person.get(2)).totalCount == 0
+        taskB.approved = true
+        taskB.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params, Person.get(2)).totalCount == 1
+
+        // Tasks assigned to a person via a group should be returned.
+        // But only if approved.
+        Person.get(2).addToPersonGroups(PersonGroup.read(1)).save(flush:true)
+        taskA.trash = false
+        taskA.approved = false
+        taskA.save(flush:true)
+        p = [personGroup: PersonGroup.read(1),
+                task: taskA,
+                estimatedHour: 2,
+                estimatedMinute: 30]
+        assert assignedGroupService.save(p).error == null
+        assert taskSearchService.getPersonsTasks(params, Person.get(2)).totalCount == 1 // Only taskB from above.
+        taskA.approved = true
+        taskA.save(flush:true)
+        assert taskSearchService.getPersonsTasks(params, Person.get(2)).totalCount == 2 // taskA and taskB.
+
+    } // testGetPersonsTasks()
+
+} // end class
Index: branches/features/taskProcedureRework/test/integration/TaskServiceTests.groovy
===================================================================
--- branches/features/taskProcedureRework/test/integration/TaskServiceTests.groovy	(revision 753)
+++ branches/features/taskProcedureRework/test/integration/TaskServiceTests.groovy	(revision 753)
@@ -0,0 +1,157 @@
+import grails.test.*
+
+/**
+* Integration tests for TaskService.
+*/
+class TaskServiceTests extends GroovyTestCase {
+
+    // Data will be saved, not rolled back.
+    // Be sure to clean up in tearDown().
+    boolean transactional = false
+
+    def taskService
+    def dateUtilService
+
+    def taskA
+    def taskB
+    def taskCount = 0
+
+    // Setup is called before each test.
+    protected void setUp() {
+        super.setUp()
+
+        // Check environment state.
+        assert Task.count() == 0
+        assert Entry.count() == 0
+        assert TaskModification.count() == 0
+
+        def p = [:]
+        def result
+
+        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
+                taskPriority:TaskPriority.get(2),
+                taskType:TaskType.get(1),
+                leadPerson:Person.get(1),
+                description:"TestA",
+                comment:"Service test task.",
+                targetStartDate: dateUtilService.today,
+                targetCompletionDate: dateUtilService.today]
+
+        result = taskService.save(p)
+        assert result.error == null
+        taskCount++
+        taskA = result.taskInstance.refresh()
+
+        p.description = "TestB"
+        result = taskService.save(p)
+        assert result.error == null
+        taskCount++
+        taskB = result.taskInstance.refresh()
+    }
+
+    // Tear down is called after each test.
+    protected void tearDown() {
+
+        taskService.delete(taskA)
+        taskService.delete(taskB)
+
+        // Ensure that we leave environment clean.
+        assert Task.count() == 0
+        assert TaskModification.count() == 0
+        assert Entry.count() == 0
+
+        super.tearDown()
+    }
+
+    def testSave() {
+
+        // Task are created by setUp().
+        assert Task.count() == taskCount
+
+        taskA.refresh()
+        assert taskA.taskModifications.size() == 1
+        assert taskA.taskModifications.each() {
+            it.taskModificationType.id == 1 // Created.
+        }
+
+        taskB.refresh()
+        assert taskB.taskModifications.size() == 1
+        assert taskB.taskModifications.each() {
+            it.taskModificationType.id == 1 // Created.
+        }
+
+    } // testSave()
+
+    void testComplete() {
+
+        def modificationCount = 0
+
+        taskA.refresh()
+        assert taskA.taskStatus ==  TaskStatus.read(1) // Not Started.
+        assert taskA.taskModifications.size() == ++modificationCount
+
+        taskService.complete(taskA)
+        taskA.refresh()
+        assert taskA.taskStatus ==  TaskStatus.read(3) // Complete.
+        assert taskA.taskModifications.size() == ++modificationCount
+
+    } // testComplete()
+
+    void testReopen() {
+
+        def entryParams = [:]
+        def modificationCount = 0
+
+        taskA.refresh()
+        assert taskA.taskStatus ==  TaskStatus.read(1) // Not Started.
+        assert taskA.taskModifications.size() == ++modificationCount
+
+        taskService.complete(taskA)
+        taskA.refresh()
+        assert taskA.taskStatus ==  TaskStatus.read(3) // Complete.
+        assert taskA.taskModifications.size() == ++modificationCount
+
+        taskService.reopen(taskA)
+        taskA.refresh()
+        assert taskA.taskStatus ==  TaskStatus.read(1) // Not Started.
+        assert taskA.taskModifications.size() == ++modificationCount
+
+        // Work Done Entry, with zero time booked.
+        entryParams = [task: taskA,
+                                        entryType: EntryType.read(3),
+                                        comment: "Test entry.",
+                                        durationHour: 0,
+                                        durationMinute: 0]
+
+        assert taskService.saveEntry(entryParams).error == null
+
+        taskService.complete(taskA)
+        taskA.refresh()
+        assert taskA.taskStatus ==  TaskStatus.read(3) // Complete.
+        assert taskA.taskModifications.size() == ++modificationCount
+
+        taskService.reopen(taskA)
+        taskA.refresh()
+        assert taskA.taskStatus ==  TaskStatus.read(1) // Not Started.
+        assert taskA.taskModifications.size() == ++modificationCount
+
+        // Work Done Entry, with time booked.
+        entryParams.durationMinute = 1
+        assert taskService.saveEntry(entryParams).error == null
+        taskA.refresh()
+        assert taskA.taskStatus ==  TaskStatus.read(2) // In Progress.
+        assert taskA.taskModifications.size() == ++modificationCount
+
+        taskService.complete(taskA)
+        taskA.refresh()
+        assert taskA.taskStatus ==  TaskStatus.read(3) // Complete.
+        assert taskA.taskModifications.size() == ++modificationCount
+
+        taskService.reopen(taskA)
+        taskA.refresh()
+        assert taskA.taskStatus ==  TaskStatus.read(2) // In Progress.
+        assert taskA.taskModifications.size() == ++modificationCount
+
+    } // testReopen()
+
+} // end class
Index: branches/features/taskProcedureRework/test/unit/AppConfigServiceTests.groovy
===================================================================
--- branches/features/taskProcedureRework/test/unit/AppConfigServiceTests.groovy	(revision 753)
+++ branches/features/taskProcedureRework/test/unit/AppConfigServiceTests.groovy	(revision 753)
@@ -0,0 +1,110 @@
+import grails.test.*
+
+/**
+* Unit tests for AppConfigService class.
+*/
+class AppConfigServiceTests extends GrailsUnitTestCase {
+
+    // Not automatically injected, assignment is bellow.
+    def appConfigService
+
+    // Some test data.
+    def configName01 = "baseDataCreated"
+    def configName02 = "dateFormat"
+    def configName03 = "blankValue"
+    def blankString = ''
+    def configDefaultValue = "true"
+    def configValue01 = "false"
+    def configValue02= "EEE, dd-MMM-yyyy"
+
+    protected void setUp() {
+        super.setUp()
+
+        // Mock the domain class.
+        mockDomain(AppConfig)
+        mockForConstraintsTests(AppConfig)
+
+        // Mock logging with debug enabled/disabled.
+        mockLogging(AppConfigService, true)
+
+        // Get an instance of the service.
+        appConfigService = new AppConfigService()
+    }
+
+    protected void tearDown() {
+        appConfigService = null
+        super.tearDown()
+    }
+
+    void testSet() {
+
+        // Set returns false for blank name.
+        assert AppConfig.list().size == 0
+        assertFalse appConfigService.set(blankString)
+        assert AppConfig.list().size == 0
+
+        // Set returns true and saves an object.
+        assertTrue appConfigService.set(configName01)
+        assert AppConfig.list().size == 1
+
+        // Set returns true and does not save a new object for existing appConfig.
+        assertTrue appConfigService.set(configName01, configValue01)
+        assert AppConfig.list().size == 1
+
+        // Set returns true and saves different objects.
+        assertTrue appConfigService.set(configName02, configValue02)
+        assert AppConfig.list().size == 2
+
+        // Set returns false when trying to set a blank value.
+        assertFalse appConfigService.set(configName03, blankString)
+        assert AppConfig.list().size == 2
+    }
+
+    void testExists() {
+
+        // Exists returns false for non existant appConfig.
+        assertFalse appConfigService.exists(configName01)
+
+        // Exists returns true for existing appConfig.
+        appConfigService.set(configName01)
+        assertTrue appConfigService.exists(configName01)
+    }
+
+    void testGetValue() {
+
+        // Get returns false for non existant appConfig.
+        assertFalse appConfigService.getValue(configName01)
+
+        // Set default and check that it returns.
+        appConfigService.set(configName01)
+        assert appConfigService.getValue(configName01) == configDefaultValue
+
+        // Set a value and check that it returns.
+        appConfigService.set(configName01, configValue01)
+        assert appConfigService.getValue(configName01) == configValue01
+    }
+
+    void testDelete() {
+
+        // Deleting returns false for non existant appConfig.
+        assert AppConfig.list().size == 0
+        assertFalse appConfigService.delete(configName01)
+
+        // First set.
+        appConfigService.set(configName01)
+        assert AppConfig.list().size == 1
+
+        // Second set.
+        appConfigService.set(configName02, configValue02)
+        assert AppConfig.list().size == 2
+
+        // Delete first set.
+        assertTrue appConfigService.delete(configName01)
+        assert AppConfig.list().size == 1
+
+        // Delete second set.
+        assertTrue appConfigService.delete(configName02)
+        assert AppConfig.list().size == 0
+    }
+
+}
Index: branches/features/taskProcedureRework/test/unit/DateUtilServiceTests.groovy
===================================================================
--- branches/features/taskProcedureRework/test/unit/DateUtilServiceTests.groovy	(revision 753)
+++ branches/features/taskProcedureRework/test/unit/DateUtilServiceTests.groovy	(revision 753)
@@ -0,0 +1,15 @@
+import grails.test.*
+
+class DateUtilServiceTests extends GrailsUnitTestCase {
+    protected void setUp() {
+        super.setUp()
+    }
+
+    protected void tearDown() {
+        super.tearDown()
+    }
+
+    void testSomething() {
+
+    }
+}
Index: branches/features/taskProcedureRework/test/unit/net/kromhouts/HqlBuilderTests.groovy
===================================================================
--- branches/features/taskProcedureRework/test/unit/net/kromhouts/HqlBuilderTests.groovy	(revision 753)
+++ branches/features/taskProcedureRework/test/unit/net/kromhouts/HqlBuilderTests.groovy	(revision 753)
@@ -0,0 +1,477 @@
+/* Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.kromhouts
+
+import org.apache.commons.logging.LogFactory
+
+/**
+ * Unit tests for HqlBuilder class.
+ * GroovyTestCase is used so that class does not depend on Grails as it may be useful outside of Grails.
+ *
+ * @author Gavin Kromhout
+ * @version DraftB
+ *
+ */
+public class HqlBuilderTests extends GroovyTestCase {
+
+    def n = '\n'
+    def t = '\t'
+    def savedMetaClass
+
+    protected void setUp() {
+        super.setUp()
+        savedMetaClass = HqlBuilder.metaClass
+        def emc = new ExpandoMetaClass(HqlBuilder, true, true)
+        emc.log = LogFactory.getLog(getClass())
+        emc.initialize()
+        GroovySystem.metaClassRegistry.setMetaClass(HqlBuilder, emc)
+    }
+
+    protected void tearDown() {
+        GroovySystem.metaClassRegistry.removeMetaClass(HqlBuilder)
+        GroovySystem.metaClassRegistry.setMetaClass(HqlBuilder, savedMetaClass)
+        super.tearDown()
+    }
+
+    void testBasicUsage() {
+
+        def q = new HqlBuilder().query {
+            select 'count(distinct book)'
+            from 'Book as book'
+            where 'book.id > 100'
+        }
+
+        assert q.query == 'select count(distinct book) from Book as book where book.id > 100'
+
+        q.select = 'distinct book'
+        assert q.query == 'select distinct book from Book as book where book.id > 100'
+        assert q.printFormattedQuery == 'select distinct book \nfrom Book as book \nwhere book.id > 100'
+
+    } // testBasicUsage()
+
+    void testBasicUsageAlternateForm() {
+
+        def q = new HqlBuilder()
+
+        q {
+            select 'distinct book'
+            from 'Book as book'
+            where 'book.id > 100'
+        }
+
+        assert q.query == 'select distinct book from Book as book where book.id > 100'
+
+    } // testBasicUsageAlternateForm()
+
+    void testPaginateParams() {
+
+        def q = new HqlBuilder(max: 99, offset: 11).query {
+            select 'distinct book'
+            from 'Book as book'
+            where 'book.id > 100'
+        }
+
+        assert q.max == 99
+        assert q.offset == 11
+
+    } // testPaginateParams()
+
+    void testPaginateParamsAlternateForm() {
+
+        def q = new HqlBuilder().query {
+            max = 99
+            offset = 11
+            select 'distinct book'
+            from 'Book as book'
+            where 'book.id > 100'
+        }
+
+        assert q.max == 99
+        assert q.offset == 11
+
+    } // testPaginateParamsAlternateForm()
+
+    void testNamedParams() {
+        def startId = 13
+        def endId = 23
+
+        def q = new HqlBuilder().query {
+            namedParams.startId = startId
+            select 'distinct book'
+            from 'Book as book'
+            where 'book.id > :startId'
+                and 'book.id < :endId'
+        }
+
+        q.namedParams.endId = endId
+
+        assert q.namedParams.startId == startId
+        assert q.namedParams.endId == endId
+
+    } // testNamedParams()
+
+    void testMultipleTerms() {
+
+        def q = new HqlBuilder().query {
+            select 'book.name',
+                        'type.name'
+            from 'Book as book',
+                    'left join book.group as group',
+                    'left join group.type as type'
+            where "book.name like '%Ned%'",
+                        'group = :group'
+        }
+
+        def expectedQuery = /select book.name, type.name from Book as book left join book.group as group left join group.type as type/
+        expectedQuery +=  / where book.name like '%Ned%' and group = :group/
+        assert q.query == expectedQuery
+
+        def expectedPrintFormat = /select book.name, ${n}${t}type.name/
+        expectedPrintFormat += / ${n}from Book as book ${n}${t}left join book.group as group ${n}${t}left join group.type as type/
+        expectedPrintFormat += / ${n}where book.name like '%Ned%' ${n}${t}and group = :group/
+        assert q.printFormattedQuery == expectedPrintFormat
+
+    } // testMultipleTerms()
+
+    void testMultipleTermsAlternateForm() {
+
+        def q = new HqlBuilder().query {
+            select 'book.name' // Create clause and append arg to clause's term list.
+            select 'type.name' // Method arg is appended to existing clause's term list.
+            from 'Book as book'
+            left 'join book.group as group'
+            left 'left join group.type as type' // 'left join' has to be repeated since left is an existing clause.
+            where(/book.name like '%Ned%'/) // Slashy string literals have to be protected when calling a method.
+            where 'group = :group'
+        }
+
+        def expectedQuery = /select book.name, type.name from Book as book left join book.group as group left join group.type as type/
+        expectedQuery +=  / where book.name like '%Ned%' and group = :group/
+        assert q.query == expectedQuery
+
+        def expectedPrintFormat = /select book.name, ${n}${t}type.name/
+        expectedPrintFormat += / ${n}from Book as book ${n}left join book.group as group ${n}${t}left join group.type as type/
+        expectedPrintFormat += / ${n}where book.name like '%Ned%' ${n}${t}and group = :group/
+        assert q.printFormattedQuery == expectedPrintFormat
+
+    } // testMultipleTermsAlternateForm()
+
+    void testPlaceHolder() {
+
+        def q = new HqlBuilder().query {
+            select 'distinct book'
+            from 'Book as book'
+            where  // Place holder as propertyMissing call.
+            order 'by book.name asc'
+        }
+
+        // Assign to place holder which is in the middle of the query string.
+        q.where = /book.name like '%Ned%'/
+
+        assert q.query == /select distinct book from Book as book where book.name like '%Ned%' order by book.name asc/
+
+    } // testPlaceHolder()
+
+    void testPlaceHolderAlternateForm() {
+
+        def q = new HqlBuilder().query {
+            select 'distinct book'
+            from 'Book as book'
+            where '' // Place holder as method call, tests for nulls when also using append method call bellow.
+            order 'by book.name asc'
+        }
+
+        // Append to place holder which is in the middle of the query string.
+        q.where(/book.name like '%Ned%'/)
+
+        assert q.query == /select distinct book from Book as book where book.name like '%Ned%' order by book.name asc/
+
+    } // testPlaceHolderAlternateForm()
+
+    void testClauseRemoval() {
+
+        def q = new HqlBuilder().query {
+            select 'count(distinct book)'
+            from 'Book as book'
+            where = /book.name like '%Ned%'/  // Slashy string literals don't need protecting when assigning.
+            order 'by book.name asc'
+        }
+
+        q.order = null // Remove clause.
+        assert q.query == /select count(distinct book) from Book as book where book.name like '%Ned%'/
+
+    } // testClauseRemoval()
+
+    void testClauseRemovalAlternateForm() {
+
+        def q = new HqlBuilder().query {
+            select 'count(distinct book)'
+            from 'Book as book'
+            where = /book.name like '%Ned%'/  // Slashy string literals don't need protecting when assigning.
+            order 'by book.name asc'
+        }
+
+        q.removeClause('order') // Remove clause, alternate form.
+        assert q.query == /select count(distinct book) from Book as book where book.name like '%Ned%'/
+
+    } // testClauseRemovalAlternateForm()
+
+    void testLogicalBuilder() {
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+            where "book.name like '%Ned%'"
+                or "book.onSpecial = true"
+        }
+
+        assert q.query == /from Book as book where book.name like '%Ned%' or book.onSpecial = true/
+
+    } // testLogicalBuilder()
+
+    void testLogicalBuilderNesting() {
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+            where "book.name like '%Ned%'"
+                or {
+                    where "book.onSpecial = true"
+                    and 'book.inStock = true'
+                }
+        }
+
+        assert q.query == /from Book as book where book.name like '%Ned%' or ( book.onSpecial = true and book.inStock = true )/
+
+    } // testLogicalBuilderNesting()
+
+    void testLogicalBuilderNestingLoop() {
+        def range = 1..2
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+            where 'book.inStock = true'
+                and {
+                    range.each {
+                        or "book.id = $it"
+                    }
+                }
+        }
+
+        assert q.query == /from Book as book where book.inStock = true and ( book.id = 1 or book.id = 2 )/
+
+    } // testLogicalBuilderNestingLoop()
+
+    void testWhereClosure() {
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+            where {
+                and 'book.id = 1'
+            }
+        }
+
+        // Only 1 expression so no brackets.
+        assert q.query == /from Book as book where book.id = 1/
+
+    } // testWhereClosure()
+
+    void testWhereClosureAlternate() {
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+        }
+
+        q.where {
+            and 'book.id = 1',
+                    'book.inStock = true'
+        }
+
+        // More than 1 expression so brackets are included.
+        assert q.query == /from Book as book where ( book.id = 1 and book.inStock = true )/
+
+    } // testWhereClosureAlternate()
+
+// This is very likely to be a common usage error as it may seem like a natural way to write the where clause.
+// Is it possible to intercept the String & GString constructors just inside the closure and call where 'book.id = 1'?
+// Perhaps by internally creating a new Closure and using something like this:
+// http://groovy.codehaus.org/JN3515-Interception ???
+// Or is it possible to examine each statement of a closure?
+    void testWhereClosureWithNewString() {
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+            where {
+                'book.id = 1' // This statement is missing a method call and hence will simply be excluded.
+                and 'book.inStock = true'
+            }
+        }
+
+        // Would be nice if the first case was true.
+        assertFalse q.query == /from Book as book where ( book.id = 1 and book.inStock = true )/
+        assert q.query == /from Book as book where book.inStock = true/
+
+    } // testSelectWhereClosureWithNewString()
+
+    void testWithConditionals() {
+        def y = true
+        def n = false
+
+        def q = new HqlBuilder().query {
+            select 'distinct book'
+            from 'Book as book'
+            if(y)
+                where(/book.name like '%Ned%'/)
+            if(n)
+                order ''
+            else
+                order 'by book.name asc'
+        }
+
+        assert q.query == /select distinct book from Book as book where book.name like '%Ned%' order by book.name asc/
+
+    } // testWithConditionals()
+
+    void testSelectWithLooping() {
+        def selections = ['id', 'name', 'description']
+
+        def q = new HqlBuilder().query {
+            for(s in selections) {
+                select "book.${s}"
+            }
+            from 'Book as book'
+        }
+
+        assert q.query == /select book.id, book.name, book.description from Book as book/
+
+    } // testSelectWithLooping()
+
+    void testWhereWithLooping() {
+        def range = 1..3
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+            where 'book.inStock = true'
+                range.each {
+                    or "book.id = $it"
+                }
+        }
+
+        assert q.query == /from Book as book where book.inStock = true or book.id = 1 or book.id = 2 or book.id = 3/
+
+    } // testWhereWithLooping()
+
+    void testWhereDirectlyWithLoops() {
+        def range = 1..3
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+            where
+                range.each {
+                    or "book.id = $it"
+                }
+        }
+
+        assert q.query == /from Book as book where book.id = 1 or book.id = 2 or book.id = 3/
+
+    } // testWhereDirectlyWithLoops()
+
+    void testWhereNodeWithLoops() {
+        def range = 1..3
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+            where {
+                range.each {
+                    or "book.id = $it"
+                }
+            }
+        }
+
+        assert q.query == /from Book as book where ( book.id = 1 or book.id = 2 or book.id = 3 )/
+
+    } // testWhereNodeWithLoops()
+
+    void testOrderByMultipleTerms() {
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+            where 'book.id > 100'
+            order 'by book.name asc',
+                        'book.id desc'
+        }
+
+        assert q.query == 'from Book as book where book.id > 100 order by book.name asc, book.id desc'
+
+        assert q.printFormattedQuery == 'from Book as book \nwhere book.id > 100 \norder by book.name asc, \n\tbook.id desc'
+
+    } // testOrderByMultipleTerms()
+
+    void testGroupByMultipleTerms() {
+
+        def q = new HqlBuilder().query {
+            from 'Book as book'
+            where 'book.id > 100'
+            group 'by book.name asc',
+                        'book.id desc'
+        }
+
+        assert q.query == 'from Book as book where book.id > 100 group by book.name asc, book.id desc'
+
+        assert q.printFormattedQuery == 'from Book as book \nwhere book.id > 100 \ngroup by book.name asc, \n\tbook.id desc'
+
+    } // testGroupByMultipleTerms()
+
+    void testUpdate() {
+        def q = new HqlBuilder().query {
+            update 'Book b'
+            set 'b.name = :newName',
+                'b.inStock = true'
+            where 'b.name = :oldName'
+        }
+
+        assert q.query == 'update Book b set b.name = :newName, b.inStock = true where b.name = :oldName'
+
+        assert q.printFormattedQuery == 'update Book b \nset b.name = :newName, \n\tb.inStock = true \nwhere b.name = :oldName'
+
+    } // testUpdate()
+
+    void testDelete() {
+        def q = new HqlBuilder().query {
+            delete 'Book b'
+            where 'b.name = :oldName'
+        }
+
+        assert q.query == 'delete Book b where b.name = :oldName'
+
+        assert q.printFormattedQuery == 'delete Book b \nwhere b.name = :oldName'
+
+    } // testDelete()
+
+    void testInsertInto() {
+        def q = new HqlBuilder().query {
+            insert 'into ArchiveBook (id, name)'
+            select 'b.id',
+                        'b.name'
+            from 'Book b'
+            where 'b.name = :oldName'
+        }
+
+        assert q.query == 'insert into ArchiveBook (id, name) select b.id, b.name from Book b where b.name = :oldName'
+
+        assert q.printFormattedQuery == 'insert into ArchiveBook (id, name) \nselect b.id, \n\tb.name \nfrom Book b \nwhere b.name = :oldName'
+
+    } // testInsertInto()
+
+} // end class
Index: branches/features/taskProcedureRework/web-app/WEB-INF/applicationContext.xml
===================================================================
--- branches/features/taskProcedureRework/web-app/WEB-INF/applicationContext.xml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/WEB-INF/applicationContext.xml	(revision 753)
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+	<bean id="grailsApplication" class="org.codehaus.groovy.grails.commons.GrailsApplicationFactoryBean">
+		<description>Grails application factory bean</description>
+        <property name="grailsDescriptor" value="/WEB-INF/grails.xml" />
+        <property name="grailsResourceLoader" ref="grailsResourceLoader" />
+	</bean>
+
+	<bean id="pluginManager" class="org.codehaus.groovy.grails.plugins.GrailsPluginManagerFactoryBean">
+		<description>A bean that manages Grails plugins</description>
+        <property name="grailsDescriptor" value="/WEB-INF/grails.xml" />
+        <property name="application" ref="grailsApplication" />
+	</bean>
+
+    <bean id="grailsConfigurator" class="org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator">
+        <constructor-arg>
+            <ref bean="grailsApplication" />
+        </constructor-arg>
+        <property name="pluginManager" ref="pluginManager" />
+    </bean>
+
+    <bean id="grailsResourceLoader" class="org.codehaus.groovy.grails.commons.GrailsResourceLoaderFactoryBean">
+        <property name="grailsResourceHolder" ref="grailsResourceHolder" />
+    </bean>
+
+    <bean id="grailsResourceHolder" scope="prototype" class="org.codehaus.groovy.grails.commons.spring.GrailsResourceHolder">
+        <property name="resources">
+              <value>classpath*:**/grails-app/**/*.groovy</value>
+        </property>
+    </bean>    
+    
+   <bean id="characterEncodingFilter"
+      class="org.springframework.web.filter.CharacterEncodingFilter">
+        <property name="encoding">
+          <value>utf-8</value>
+        </property>
+   </bean>    	
+</beans>
Index: branches/features/taskProcedureRework/web-app/WEB-INF/sitemesh.xml
===================================================================
--- branches/features/taskProcedureRework/web-app/WEB-INF/sitemesh.xml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/WEB-INF/sitemesh.xml	(revision 753)
@@ -0,0 +1,14 @@
+<sitemesh>
+    <page-parsers>
+        <parser content-type="text/html"
+            class="org.codehaus.groovy.grails.web.sitemesh.GrailsHTMLPageParser" />
+        <parser content-type="text/html;charset=ISO-8859-1"
+            class="org.codehaus.groovy.grails.web.sitemesh.GrailsHTMLPageParser" />
+        <parser content-type="text/html;charset=UTF-8"
+            class="org.codehaus.groovy.grails.web.sitemesh.GrailsHTMLPageParser" />            
+    </page-parsers>
+
+    <decorator-mappers>
+        <mapper class="org.codehaus.groovy.grails.web.sitemesh.GrailsLayoutDecoratorMapper" />
+    </decorator-mappers>
+</sitemesh>
Index: branches/features/taskProcedureRework/web-app/WEB-INF/tld/c.tld
===================================================================
--- branches/features/taskProcedureRework/web-app/WEB-INF/tld/c.tld	(revision 753)
+++ branches/features/taskProcedureRework/web-app/WEB-INF/tld/c.tld	(revision 753)
@@ -0,0 +1,563 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
+    version="2.0">
+    
+  <description>JSTL 1.1 core library</description>
+  <display-name>JSTL core</display-name>
+  <tlib-version>1.1</tlib-version>
+  <short-name>c</short-name>
+  <uri>http://java.sun.com/jsp/jstl/core</uri>
+
+  <validator>
+    <description>
+        Provides core validation features for JSTL tags.
+    </description>
+    <validator-class>
+        org.apache.taglibs.standard.tlv.JstlCoreTLV
+    </validator-class>
+  </validator>
+
+  <tag>
+    <description>
+        Catches any Throwable that occurs in its body and optionally
+        exposes it.
+    </description>
+    <name>catch</name>
+    <tag-class>org.apache.taglibs.standard.tag.common.core.CatchTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Name of the exported scoped variable for the
+exception thrown from a nested action. The type of the
+scoped variable is the type of the exception thrown.
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+	Simple conditional tag that establishes a context for
+	mutually exclusive conditional operations, marked by
+	&lt;when&gt; and &lt;otherwise&gt;
+    </description>
+    <name>choose</name>
+    <tag-class>org.apache.taglibs.standard.tag.common.core.ChooseTag</tag-class>
+    <body-content>JSP</body-content>
+  </tag>
+
+  <tag>
+    <description>
+	Simple conditional tag, which evalutes its body if the
+	supplied condition is true and optionally exposes a Boolean
+	scripting variable representing the evaluation of this condition
+    </description>
+    <name>if</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.core.IfTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+The test condition that determines whether or
+not the body content should be processed.
+        </description>
+        <name>test</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+	<type>boolean</type>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable for the
+resulting value of the test condition. The type
+of the scoped variable is Boolean.        
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope for var.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Retrieves an absolute or relative URL and exposes its contents
+        to either the page, a String in 'var', or a Reader in 'varReader'.
+    </description>
+    <name>import</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.core.ImportTag</tag-class>
+    <tei-class>org.apache.taglibs.standard.tei.ImportTEI</tei-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+The URL of the resource to import.
+        </description>
+        <name>url</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable for the
+resource's content. The type of the scoped
+variable is String.
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope for var.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable for the
+resource's content. The type of the scoped
+variable is Reader.
+        </description>
+        <name>varReader</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the context when accessing a relative
+URL resource that belongs to a foreign
+context.
+        </description>
+        <name>context</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Character encoding of the content at the input
+resource.
+        </description>
+        <name>charEncoding</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+	The basic iteration tag, accepting many different
+        collection types and supporting subsetting and other
+        functionality
+    </description>
+    <name>forEach</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.core.ForEachTag</tag-class>
+    <tei-class>org.apache.taglibs.standard.tei.ForEachTEI</tei-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Collection of items to iterate over.
+        </description>
+	<name>items</name>
+	<required>false</required>
+	<rtexprvalue>true</rtexprvalue>
+	<type>java.lang.Object</type>
+    </attribute>
+    <attribute>
+        <description>
+If items specified:
+Iteration begins at the item located at the
+specified index. First item of the collection has
+index 0.
+If items not specified:
+Iteration begins with index set at the value
+specified.
+        </description>
+	<name>begin</name>
+	<required>false</required>
+	<rtexprvalue>true</rtexprvalue>
+	<type>int</type>
+    </attribute>
+    <attribute>
+        <description>
+If items specified:
+Iteration ends at the item located at the
+specified index (inclusive).
+If items not specified:
+Iteration ends when index reaches the value
+specified.
+        </description>
+	<name>end</name>
+	<required>false</required>
+	<rtexprvalue>true</rtexprvalue>
+	<type>int</type>
+    </attribute>
+    <attribute>
+        <description>
+Iteration will only process every step items of
+the collection, starting with the first one.
+        </description>
+	<name>step</name>
+	<required>false</required>
+	<rtexprvalue>true</rtexprvalue>
+	<type>int</type>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable for the
+current item of the iteration. This scoped
+variable has nested visibility. Its type depends
+on the object of the underlying collection.
+        </description>
+	<name>var</name>
+	<required>false</required>
+	<rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable for the
+status of the iteration. Object exported is of type
+javax.servlet.jsp.jstl.core.LoopTagStatus. This scoped variable has nested
+visibility.
+        </description>
+	<name>varStatus</name>
+	<required>false</required>
+	<rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+	Iterates over tokens, separated by the supplied delimeters
+    </description>
+    <name>forTokens</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.core.ForTokensTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+String of tokens to iterate over.
+        </description>
+	<name>items</name>
+	<required>true</required>
+	<rtexprvalue>true</rtexprvalue>
+	<type>java.lang.String</type>
+    </attribute>
+    <attribute>
+        <description>
+The set of delimiters (the characters that
+separate the tokens in the string).
+        </description>
+	<name>delims</name>
+	<required>true</required>
+	<rtexprvalue>true</rtexprvalue>
+	<type>java.lang.String</type>
+    </attribute>
+    <attribute>
+        <description>
+Iteration begins at the token located at the
+specified index. First token has index 0.
+        </description>
+	<name>begin</name>
+	<required>false</required>
+	<rtexprvalue>true</rtexprvalue>
+	<type>int</type>
+    </attribute>
+    <attribute>
+        <description>
+Iteration ends at the token located at the
+specified index (inclusive).
+        </description>
+	<name>end</name>
+	<required>false</required>
+	<rtexprvalue>true</rtexprvalue>
+	<type>int</type>
+    </attribute>
+    <attribute>
+        <description>
+Iteration will only process every step tokens
+of the string, starting with the first one.
+        </description>
+	<name>step</name>
+	<required>false</required>
+	<rtexprvalue>true</rtexprvalue>
+	<type>int</type>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable for the
+current item of the iteration. This scoped
+variable has nested visibility.
+        </description>
+	<name>var</name>
+	<required>false</required>
+	<rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable for the
+status of the iteration. Object exported is of
+type
+javax.servlet.jsp.jstl.core.LoopTag
+Status. This scoped variable has nested
+visibility.
+        </description>
+	<name>varStatus</name>
+	<required>false</required>
+	<rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Like &lt;%= ... &gt;, but for expressions.
+    </description> 
+    <name>out</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.core.OutTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Expression to be evaluated.
+        </description>
+        <name>value</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Default value if the resulting value is null.
+        </description>
+        <name>default</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Determines whether characters &lt;,&gt;,&amp;,'," in the
+resulting string should be converted to their
+corresponding character entity codes. Default value is
+true.
+        </description>
+        <name>escapeXml</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+  </tag>
+
+
+  <tag>
+    <description>
+        Subtag of &lt;choose&gt; that follows &lt;when&gt; tags
+        and runs only if all of the prior conditions evaluated to
+        'false'
+    </description>
+    <name>otherwise</name>
+    <tag-class>org.apache.taglibs.standard.tag.common.core.OtherwiseTag</tag-class>
+    <body-content>JSP</body-content>
+  </tag>
+
+  <tag>
+    <description>
+        Adds a parameter to a containing 'import' tag's URL.
+    </description>
+    <name>param</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.core.ParamTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Name of the query string parameter.
+        </description>
+        <name>name</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Value of the parameter.
+        </description>
+        <name>value</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Redirects to a new URL.
+    </description>
+    <name>redirect</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.core.RedirectTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+The URL of the resource to redirect to.
+        </description>
+        <name>url</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the context when redirecting to a relative URL
+resource that belongs to a foreign context.
+        </description>
+        <name>context</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Removes a scoped variable (from a particular scope, if specified).
+    </description>
+    <name>remove</name>
+    <tag-class>org.apache.taglibs.standard.tag.common.core.RemoveTag</tag-class>
+    <body-content>empty</body-content>
+    <attribute>
+        <description>
+Name of the scoped variable to be removed.
+        </description>
+        <name>var</name>
+        <required>true</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope for var.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+ <tag>
+    <description>
+        Sets the result of an expression evaluation in a 'scope'
+    </description>
+    <name>set</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.core.SetTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Name of the exported scoped variable to hold the value
+specified in the action. The type of the scoped variable is
+whatever type the value expression evaluates to.
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Expression to be evaluated.
+        </description>
+        <name>value</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Target object whose property will be set. Must evaluate to
+a JavaBeans object with setter property property, or to a
+java.util.Map object.
+        </description>
+        <name>target</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the property to be set in the target object.
+        </description>
+        <name>property</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope for var.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Creates a URL with optional query parameters.
+    </description>
+    <name>url</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.core.UrlTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Name of the exported scoped variable for the
+processed url. The type of the scoped variable is
+String.
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope for var.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+URL to be processed.
+        </description>
+        <name>value</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the context when specifying a relative URL
+resource that belongs to a foreign context.
+        </description>
+        <name>context</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+	Subtag of &lt;choose&gt; that includes its body if its
+	condition evalutes to 'true'
+    </description>
+    <name>when</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.core.WhenTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+The test condition that determines whether or not the
+body content should be processed.
+        </description>
+        <name>test</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+	<type>boolean</type>
+    </attribute>
+  </tag>
+
+</taglib>
Index: branches/features/taskProcedureRework/web-app/WEB-INF/tld/fmt.tld
===================================================================
--- branches/features/taskProcedureRework/web-app/WEB-INF/tld/fmt.tld	(revision 753)
+++ branches/features/taskProcedureRework/web-app/WEB-INF/tld/fmt.tld	(revision 753)
@@ -0,0 +1,671 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
+    version="2.0">
+    
+  <description>JSTL 1.1 i18n-capable formatting library</description>
+  <display-name>JSTL fmt</display-name>
+  <tlib-version>1.1</tlib-version>
+  <short-name>fmt</short-name>
+  <uri>http://java.sun.com/jsp/jstl/fmt</uri>
+
+  <validator>
+    <description>
+        Provides core validation features for JSTL tags.
+    </description>
+    <validator-class>
+        org.apache.taglibs.standard.tlv.JstlFmtTLV
+    </validator-class>
+  </validator>
+
+  <tag>
+    <description>
+        Sets the request character encoding
+    </description>
+    <name>requestEncoding</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.RequestEncodingTag</tag-class>
+    <body-content>empty</body-content>
+    <attribute>
+        <description>
+Name of character encoding to be applied when
+decoding request parameters.
+        </description>
+        <name>value</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Stores the given locale in the locale configuration variable
+    </description>
+    <name>setLocale</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.SetLocaleTag</tag-class>
+    <body-content>empty</body-content>
+    <attribute>
+        <description>
+A String value is interpreted as the
+printable representation of a locale, which
+must contain a two-letter (lower-case)
+language code (as defined by ISO-639),
+and may contain a two-letter (upper-case)
+country code (as defined by ISO-3166).
+Language and country codes must be
+separated by hyphen (-) or underscore
+(_).        
+	</description>
+        <name>value</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Vendor- or browser-specific variant.
+See the java.util.Locale javadocs for
+more information on variants.
+        </description>
+        <name>variant</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope of the locale configuration variable.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Specifies the time zone for any time formatting or parsing actions
+        nested in its body
+    </description>
+    <name>timeZone</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.TimeZoneTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+The time zone. A String value is interpreted as
+a time zone ID. This may be one of the time zone
+IDs supported by the Java platform (such as
+"America/Los_Angeles") or a custom time zone
+ID (such as "GMT-8"). See
+java.util.TimeZone for more information on
+supported time zone formats.
+        </description>
+        <name>value</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Stores the given time zone in the time zone configuration variable
+    </description>
+    <name>setTimeZone</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.SetTimeZoneTag</tag-class>
+    <body-content>empty</body-content>
+    <attribute>
+        <description>
+The time zone. A String value is interpreted as
+a time zone ID. This may be one of the time zone
+IDs supported by the Java platform (such as
+"America/Los_Angeles") or a custom time zone
+ID (such as "GMT-8"). See java.util.TimeZone for
+more information on supported time zone
+formats.
+        </description>
+        <name>value</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable which
+stores the time zone of type
+java.util.TimeZone.
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope of var or the time zone configuration
+variable.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Loads a resource bundle to be used by its tag body
+    </description>
+    <name>bundle</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.BundleTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Resource bundle base name. This is the bundle's
+fully-qualified resource name, which has the same
+form as a fully-qualified class name, that is, it uses
+"." as the package component separator and does not
+have any file type (such as ".class" or ".properties")
+suffix.
+        </description>
+        <name>basename</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Prefix to be prepended to the value of the message
+key of any nested &lt;fmt:message&gt; action.
+        </description>
+        <name>prefix</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Loads a resource bundle and stores it in the named scoped variable or
+        the bundle configuration variable
+    </description>
+    <name>setBundle</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.SetBundleTag</tag-class>
+    <body-content>empty</body-content>
+    <attribute>
+        <description>
+Resource bundle base name. This is the bundle's
+fully-qualified resource name, which has the same
+form as a fully-qualified class name, that is, it uses
+"." as the package component separator and does not
+have any file type (such as ".class" or ".properties")
+suffix.
+        </description>
+        <name>basename</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable which stores
+the i18n localization context of type
+javax.servlet.jsp.jstl.fmt.LocalizationC
+ontext.
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope of var or the localization context
+configuration variable.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Maps key to localized message and performs parametric replacement
+    </description>
+    <name>message</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.MessageTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Message key to be looked up.
+        </description>
+        <name>key</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Localization context in whose resource
+bundle the message key is looked up.
+        </description>
+        <name>bundle</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable
+which stores the localized message.
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope of var.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Supplies an argument for parametric replacement to a containing
+        &lt;message&gt; tag
+    </description>
+    <name>param</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.ParamTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Argument used for parametric replacement.
+        </description>
+        <name>value</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Formats a numeric value as a number, currency, or percentage
+    </description>
+    <name>formatNumber</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.FormatNumberTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Numeric value to be formatted.
+        </description>
+        <name>value</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Specifies whether the value is to be
+formatted as number, currency, or
+percentage.
+        </description>
+        <name>type</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Custom formatting pattern.
+        </description>
+        <name>pattern</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+ISO 4217 currency code. Applied only
+when formatting currencies (i.e. if type is
+equal to "currency"); ignored otherwise.
+        </description>
+        <name>currencyCode</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Currency symbol. Applied only when
+formatting currencies (i.e. if type is equal
+to "currency"); ignored otherwise.
+        </description>
+        <name>currencySymbol</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Specifies whether the formatted output
+will contain any grouping separators.
+        </description>
+        <name>groupingUsed</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Maximum number of digits in the integer
+portion of the formatted output.
+        </description>
+        <name>maxIntegerDigits</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Minimum number of digits in the integer
+portion of the formatted output.
+        </description>
+        <name>minIntegerDigits</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Maximum number of digits in the
+fractional portion of the formatted output.
+        </description>
+        <name>maxFractionDigits</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Minimum number of digits in the
+fractional portion of the formatted output.
+        </description>
+        <name>minFractionDigits</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable
+which stores the formatted result as a
+String.
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope of var.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Parses the string representation of a number, currency, or percentage
+    </description>
+    <name>parseNumber</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.ParseNumberTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+String to be parsed.
+        </description>
+        <name>value</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Specifies whether the string in the value
+attribute should be parsed as a number,
+currency, or percentage.
+        </description>
+        <name>type</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Custom formatting pattern that determines
+how the string in the value attribute is to be
+parsed.
+        </description>
+        <name>pattern</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Locale whose default formatting pattern (for
+numbers, currencies, or percentages,
+respectively) is to be used during the parse
+operation, or to which the pattern specified
+via the pattern attribute (if present) is
+applied.
+        </description>
+        <name>parseLocale</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Specifies whether just the integer portion of
+the given value should be parsed.
+        </description>
+        <name>integerOnly</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable which
+stores the parsed result (of type
+java.lang.Number).
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope of var.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Formats a date and/or time using the supplied styles and pattern
+    </description>
+    <name>formatDate</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.FormatDateTag</tag-class>
+    <body-content>empty</body-content>
+    <attribute>
+        <description>
+Date and/or time to be formatted.
+        </description>
+        <name>value</name>
+        <required>true</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Specifies whether the time, the date, or both
+the time and date components of the given
+date are to be formatted. 
+        </description>
+        <name>type</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Predefined formatting style for dates. Follows
+the semantics defined in class
+java.text.DateFormat. Applied only
+when formatting a date or both a date and
+time (i.e. if type is missing or is equal to
+"date" or "both"); ignored otherwise.
+        </description>
+        <name>dateStyle</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Predefined formatting style for times. Follows
+the semantics defined in class
+java.text.DateFormat. Applied only
+when formatting a time or both a date and
+time (i.e. if type is equal to "time" or "both");
+ignored otherwise.
+        </description>
+        <name>timeStyle</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Custom formatting style for dates and times.
+        </description>
+        <name>pattern</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Time zone in which to represent the formatted
+time.
+        </description>
+        <name>timeZone</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable which
+stores the formatted result as a String.
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope of var.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+  <tag>
+    <description>
+        Parses the string representation of a date and/or time
+    </description>
+    <name>parseDate</name>
+    <tag-class>org.apache.taglibs.standard.tag.rt.fmt.ParseDateTag</tag-class>
+    <body-content>JSP</body-content>
+    <attribute>
+        <description>
+Date string to be parsed.
+        </description>
+        <name>value</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Specifies whether the date string in the
+value attribute is supposed to contain a
+time, a date, or both.
+        </description>
+        <name>type</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Predefined formatting style for days
+which determines how the date
+component of the date string is to be
+parsed. Applied only when formatting a
+date or both a date and time (i.e. if type
+is missing or is equal to "date" or "both");
+ignored otherwise.
+        </description>
+        <name>dateStyle</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Predefined formatting styles for times
+which determines how the time
+component in the date string is to be
+parsed. Applied only when formatting a
+time or both a date and time (i.e. if type
+is equal to "time" or "both"); ignored
+otherwise.
+        </description>
+        <name>timeStyle</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Custom formatting pattern which
+determines how the date string is to be
+parsed.
+        </description>
+        <name>pattern</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Time zone in which to interpret any time
+information in the date string.
+        </description>
+        <name>timeZone</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Locale whose predefined formatting styles
+for dates and times are to be used during
+the parse operation, or to which the
+pattern specified via the pattern
+attribute (if present) is applied.
+        </description>
+        <name>parseLocale</name>
+        <required>false</required>
+        <rtexprvalue>true</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Name of the exported scoped variable in
+which the parsing result (of type
+java.util.Date) is stored.
+        </description>
+        <name>var</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+    <attribute>
+        <description>
+Scope of var.
+        </description>
+        <name>scope</name>
+        <required>false</required>
+        <rtexprvalue>false</rtexprvalue>
+    </attribute>
+  </tag>
+
+</taglib>
Index: branches/features/taskProcedureRework/web-app/WEB-INF/tld/grails.tld
===================================================================
--- branches/features/taskProcedureRework/web-app/WEB-INF/tld/grails.tld	(revision 753)
+++ branches/features/taskProcedureRework/web-app/WEB-INF/tld/grails.tld	(revision 753)
@@ -0,0 +1,551 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
+            http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
+        version="2.0">
+    <description>The Grails (Groovy on Rails) custom tag library</description>
+    <tlib-version>0.2</tlib-version>
+    <short-name>grails</short-name>
+    <uri>http://grails.codehaus.org/tags</uri>
+
+
+    <tag>
+        <name>link</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspLinkTag</tag-class>
+        <body-content>JSP</body-content>
+        <attribute>
+            <name>action</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>controller</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>id</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>url</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>params</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>form</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspFormTag</tag-class>
+        <body-content>JSP</body-content>
+        <attribute>
+            <name>action</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>controller</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>id</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>url</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>method</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>select</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspSelectTag</tag-class>
+        <body-content>JSP</body-content>
+        <attribute>
+            <name>name</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>value</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>optionKey</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>optionValue</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>datePicker</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspDatePickerTag</tag-class>
+        <body-content>empty</body-content>
+        <attribute>
+            <name>name</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>value</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>precision</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>false</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>currencySelect</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspCurrencySelectTag</tag-class>
+        <body-content>empty</body-content>
+        <attribute>
+            <name>name</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>value</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>localeSelect</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspLocaleSelectTag</tag-class>
+        <body-content>empty</body-content>
+        <attribute>
+            <name>name</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>value</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>timeZoneSelect</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspTimeZoneSelectTag</tag-class>
+        <body-content>empty</body-content>
+        <attribute>
+            <name>name</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>value</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>checkBox</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspCheckboxTag</tag-class>
+        <body-content>empty</body-content>
+        <attribute>
+            <name>name</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>value</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>hasErrors</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspHasErrorsTag</tag-class>
+        <body-content>JSP</body-content>
+        <attribute>
+            <name>model</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>bean</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>field</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>false</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>eachError</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspEachErrorTag</tag-class>
+        <body-content>JSP</body-content>
+        <attribute>
+            <name>model</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>bean</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>field</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>false</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>renderErrors</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspEachErrorTag</tag-class>
+        <body-content>JSP</body-content>
+        <attribute>
+            <name>model</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>bean</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>field</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>as</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>false</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>message</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspMessageTag</tag-class>
+        <body-content>JSP</body-content>
+        <attribute>
+            <name>code</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>error</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>default</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>false</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>remoteFunction</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspRemoteFunctionTag</tag-class>
+        <body-content>empty</body-content>
+        <attribute>
+            <name>before</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>after</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>action</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>controller</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>id</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>url</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>params</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>asynchronous</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>method</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>update</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onSuccess</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onFailure</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onComplete</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onLoading</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onLoaded</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onInteractive</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>remoteLink</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspRemoteLinkTag</tag-class>
+        <body-content>JSP</body-content>
+        <attribute>
+            <name>before</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>after</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>action</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>controller</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>id</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>url</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>params</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>asynchronous</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>method</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>update</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onSuccess</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onFailure</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onComplete</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onLoading</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onLoaded</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onInteractive</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>formRemote</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspFormRemoteTag</tag-class>
+        <body-content>JSP</body-content>
+        <attribute>
+            <name>before</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>after</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>action</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>controller</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>id</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>url</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>params</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>asynchronous</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>method</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>update</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onSuccess</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onFailure</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onComplete</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onLoading</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onLoaded</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <attribute>
+            <name>onInteractive</name>
+            <required>false</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+    <tag>
+        <name>invokeTag</name>
+        <tag-class>org.codehaus.groovy.grails.web.taglib.jsp.JspInvokeGrailsTagLibTag</tag-class>
+        <body-content>JSP</body-content>
+        <variable>
+            <name-given>it</name-given>
+            <variable-class>java.lang.Object</variable-class>
+            <declare>true</declare>
+            <scope>NESTED</scope>
+        </variable>
+        <attribute>
+            <name>tagName</name>
+            <required>true</required>
+            <rtexprvalue>true</rtexprvalue>
+        </attribute>
+        <dynamic-attributes>true</dynamic-attributes>
+    </tag>
+</taglib>
+
Index: branches/features/taskProcedureRework/web-app/WEB-INF/tld/spring.tld
===================================================================
--- branches/features/taskProcedureRework/web-app/WEB-INF/tld/spring.tld	(revision 753)
+++ branches/features/taskProcedureRework/web-app/WEB-INF/tld/spring.tld	(revision 753)
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
+
+<taglib>
+
+	<tlib-version>1.1.1</tlib-version>
+
+	<jsp-version>1.2</jsp-version>
+
+	<short-name>Spring</short-name>
+
+	<uri>http://www.springframework.org/tags</uri>
+
+	<description>Spring Framework JSP Tag Library. Authors: Rod Johnson, Juergen Hoeller</description>
+
+
+	<tag>
+
+		<name>htmlEscape</name>
+		<tag-class>org.springframework.web.servlet.tags.HtmlEscapeTag</tag-class>
+		<body-content>JSP</body-content>
+
+		<description>
+			Sets default HTML escape value for the current page.
+			Overrides a "defaultHtmlEscape" context-param in web.xml, if any.
+		</description>
+
+		<attribute>
+			<name>defaultHtmlEscape</name>
+			<required>true</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+	</tag>
+
+
+	<tag>
+
+		<name>escapeBody</name>
+		<tag-class>org.springframework.web.servlet.tags.EscapeBodyTag</tag-class>
+		<body-content>JSP</body-content>
+
+		<description>
+			Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping.
+			The HTML escaping flag participates in a page-wide or application-wide setting
+			(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+		</description>
+
+		<attribute>
+			<name>htmlEscape</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>javaScriptEscape</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+	</tag>
+
+
+	<tag>
+
+		<name>message</name>
+		<tag-class>org.springframework.web.servlet.tags.MessageTag</tag-class>
+		<body-content>JSP</body-content>
+
+		<description>
+			Retrieves the message with the given code, or text if code isn't resolvable.
+			The HTML escaping flag participates in a page-wide or application-wide setting
+			(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+		</description>
+
+		<attribute>
+			<name>code</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>arguments</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>text</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>var</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>scope</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>htmlEscape</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>javaScriptEscape</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+	</tag>
+
+
+	<tag>
+
+		<name>theme</name>
+		<tag-class>org.springframework.web.servlet.tags.ThemeTag</tag-class>
+		<body-content>JSP</body-content>
+
+		<description>
+			Retrieves the theme message with the given code, or text if code isn't resolvable.
+			The HTML escaping flag participates in a page-wide or application-wide setting
+			(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+		</description>
+
+		<attribute>
+			<name>code</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>arguments</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>text</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>var</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>scope</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>htmlEscape</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>javaScriptEscape</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+	</tag>
+
+
+	<tag>
+
+		<name>hasBindErrors</name>
+		<tag-class>org.springframework.web.servlet.tags.BindErrorsTag</tag-class>
+		<body-content>JSP</body-content>
+
+		<description>
+			Provides Errors instance in case of bind errors.
+			The HTML escaping flag participates in a page-wide or application-wide setting
+			(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+		</description>
+
+		<variable>
+			<name-given>errors</name-given>
+			<variable-class>org.springframework.validation.Errors</variable-class>
+		</variable>
+
+		<attribute>
+			<name>name</name>
+			<required>true</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>htmlEscape</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+	</tag>
+
+
+	<tag>
+
+		<name>nestedPath</name>
+		<tag-class>org.springframework.web.servlet.tags.NestedPathTag</tag-class>
+		<body-content>JSP</body-content>
+
+		<description>
+			Sets a nested path to be used by the bind tag's path.
+		</description>
+
+		<variable>
+			<name-given>nestedPath</name-given>
+			<variable-class>java.lang.String</variable-class>
+		</variable>
+
+		<attribute>
+			<name>path</name>
+			<required>true</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+	</tag>
+
+
+	<tag>
+
+		<name>bind</name>
+		<tag-class>org.springframework.web.servlet.tags.BindTag</tag-class>
+		<body-content>JSP</body-content>
+
+		<description>
+			Provides BindStatus object for the given bind path.
+			The HTML escaping flag participates in a page-wide or application-wide setting
+			(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+		</description>
+
+		<variable>
+			<name-given>status</name-given>
+			<variable-class>org.springframework.web.servlet.support.BindStatus</variable-class>
+		</variable>
+
+		<attribute>
+			<name>path</name>
+			<required>true</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>ignoreNestedPath</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>htmlEscape</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+	</tag>
+
+
+	<tag>
+
+		<name>transform</name>
+		<tag-class>org.springframework.web.servlet.tags.TransformTag</tag-class>
+		<body-content>JSP</body-content>
+
+		<description>
+			Provides transformation of variables to Strings, using an appropriate
+			custom PropertyEditor from BindTag (can only be used inside BindTag).
+			The HTML escaping flag participates in a page-wide or application-wide setting
+			(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
+		</description>
+
+		<attribute>
+			<name>value</name>
+			<required>true</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>var</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>scope</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+		<attribute>
+			<name>htmlEscape</name>
+			<required>false</required>
+			<rtexprvalue>true</rtexprvalue>
+		</attribute>
+
+	</tag>
+
+</taglib>
Index: branches/features/taskProcedureRework/web-app/css/calendarmonthviewCustom.css
===================================================================
--- branches/features/taskProcedureRework/web-app/css/calendarmonthviewCustom.css	(revision 753)
+++ branches/features/taskProcedureRework/web-app/css/calendarmonthviewCustom.css	(revision 753)
@@ -0,0 +1,78 @@
+/* Calendar */
+
+/* Link size and color */
+.calendar a {
+    font-weight: normal;
+    font-size: 12px;
+    color: #000000;
+    text-decoration: none;
+}
+
+.calendar li:hover a{
+    color: red;
+}
+
+.calendar li:hover {
+    color: red;
+}
+
+/* Table  */
+table.calendar td.dayWithItems {
+    background: #ffed8c;
+    border: 1px solid #ffde33;
+}
+table.calendar td.outsideOfMonth {
+    background: #BBBBBB;
+}
+
+table.calendar td.today {
+    background: #B2D1FF;
+}
+
+table.calendar .oddDay {
+    background: #efefef;
+}
+
+table.calendar .evenDay {
+    background: #f7f7f7;
+}
+
+table.calendar td.day {
+    /*
+    height: 12.5%;
+    width: 12.5%;
+    */
+    height: 7em;
+    width: 7em;
+}
+
+table.calendar td.weekOfYear {
+    height: 5%;
+    width: 5%;
+}
+
+/* Day title */
+table.calendar h1 {
+    color:#5C5C5C;
+}
+table.calendar h1:hover {
+    color: red;
+}
+
+table.calendar th:hover, table.calendar td:hover {
+
+}
+
+table.calendar {
+    border-collapse: collapse;
+}
+
+table.calendar th, table.calendar td {
+    border-left:1px solid #DDDDDD;
+}
+
+/* Month Control Title*/
+span.calendarMonthControlTitle {
+    font-size: 17px;
+    font-weight: bold;
+}
Index: branches/features/taskProcedureRework/web-app/css/lightbox.css
===================================================================
--- branches/features/taskProcedureRework/web-app/css/lightbox.css	(revision 753)
+++ branches/features/taskProcedureRework/web-app/css/lightbox.css	(revision 753)
@@ -0,0 +1,88 @@
+#lightbox {
+  position: absolute;
+  left: 0;
+  width: 100%;
+  text-align: center;
+  line-height: 0;
+  overflow: auto;
+  z-index: 100;
+}
+
+#lightbox a img { border: none; }
+
+#outerImageContainer {
+  position: relative;
+  background-color: #fff;
+  width: 250px;
+  height: 250px;
+  margin: 0 auto;
+}
+
+#imageContainer {
+  padding: 10px;
+}
+
+#loading {
+  position: absolute;
+  top: 40%;
+  left: 0%;
+  height: 25%;
+  width: 100%;
+  text-align: center;
+  line-height: 0;
+  background: transparent url("../images/loading.gif") center center no-repeat;
+}
+
+#hoverNav {
+    position: absolute;
+    top: 0;
+    left: 0;
+    height: 100%;
+    width: 100%;
+    z-index: 10;
+}
+
+#imageContainer > #hoverNav { left: 0; }
+#hoverNav a { outline: none; }
+
+#prevLink, #nextLink {
+  width: 49%;
+  height: 100%;
+  background: transparent url("../images/blank.gif") no-repeat; /* Trick IE into showing hover */
+  display: block;
+}
+#prevLink { left: 0; float: left; }
+#nextLink { right: 0; float: right; }
+#prevLink:hover, #prevLink:visited:hover { background: url("../images/prevlabel.gif") left 15% no-repeat; }
+#nextLink:hover, #nextLink:visited:hover { background: url("../images/nextlabel.gif") right 15% no-repeat; }
+
+#imageDataContainer {
+  font: 10px Verdana, Helvetica, sans-serif;
+  background-color: #fff;
+  margin: 0 auto;
+  line-height: 1.4em;
+  width: 100%
+}
+
+#imageData { padding: 0 10px; color: #666; text-align: center; }
+#imageData #imageDetails { float: left; text-align: left; }	
+#imageData #caption { font-weight: bold; }
+#imageData #numberDisplay { display: block; clear: left; padding-bottom: 1.0em;	}			
+#imageData #bottomNav { float: right; text-align: right; } 
+
+#imageData #bottomNavClose { cursor: pointer; }
+
+#imageData #bottomNavNext, #imageData #bottomNavPrev { 
+  cursor: pointer;
+  padding: 5px 2px;
+}
+
+#overlay {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 90;
+  width: 100%;
+  height: 500px;
+  background-color: #000;
+}
Index: branches/features/taskProcedureRework/web-app/css/main.css
===================================================================
--- branches/features/taskProcedureRework/web-app/css/main.css	(revision 753)
+++ branches/features/taskProcedureRework/web-app/css/main.css	(revision 753)
@@ -0,0 +1,747 @@
+html * {
+    margin: 0;
+    /*padding: 0; SELECT NOT DISPLAYED CORRECTLY IN FIREFOX */
+
+}
+
+/**
+* GENERAL.
+* Commonly used application colours:
+* #FF9900 - Traffic Light Amber.
+* #00CC00 - Traffic Light Green.
+* #FF0000 - Traffic Light Red.
+* #2647A0 - Dark Blue (Tabs).
+* #006DBA - Link Blue (Links and Message Text).
+* #CC0000 - Dark Red (Error Message Text).
+* #FCFCFC - Off White (Input Fields).
+* #666666 - Dark Grey (Nav Text).
+* #333333 - Very Dark Grey (TH, Menu Button).
+* #FFFFFF - Table Row (Even).
+* #F7F7F7 - Table Row (Odd).
+* #EDEDED - Total Row Grey (Bg).
+* #555555 - Total Row Grey (Fg).
+*/
+
+.spinner {
+    padding: 10px 0 0 18px;
+    position: absolute;
+}
+
+body {
+    text-align: center;
+    color: #222;
+    font: 14px verdana, arial, helvetica, sans-serif;
+    background: transparent url("../images/brushed_metal.png") repeat fixed center;
+}
+
+#wrapper {
+  margin: 0 auto;
+  padding: 0;
+  width: 1024px;
+}
+
+#top {
+  background: url("../images/topBg.png") no-repeat scroll center;
+  width: 1020px;
+  height: 31px;
+}
+
+#content {
+  padding: 0px 20px 20px;
+  background: url("../images/contentbg.png") repeat-y scroll center;
+  width: 980px;
+  /*border: 1px solid #ccc;*/
+}
+
+#Header {
+  background: transparent url("../images/logo.png") no-repeat scroll center;
+  width: 980px;
+  height: 136px;
+}
+#HeaderDev {
+  background: transparent url("../images/logoDev.png") no-repeat scroll center;
+  width: 980px;
+  height: 136px;
+}
+#HeaderLink{
+  display: block;
+  width: 958px;
+  height: 136px;
+}
+
+/* Navigation plugin, top level. */
+#menu {
+    float: left;
+    /*border: 1px solid #ccc;*/
+}
+
+/* Application log textarea */
+#log {
+    width: 920px;
+    height: auto;
+}
+
+div.tabHeader {
+    padding: 5px 15px 0px 15px;
+}
+.tabHeader h1 {
+    color: #2647a0;
+    font-weight: bold;
+    font-size: 17px;
+    margin: 0 0 .3em 0;
+}
+.tabHeader h2 {
+    color: #2647a0;
+    font-weight: normal;
+    font-size: 15px;
+    margin: 0 0 .3em 0;
+}
+
+a:link, a:visited, a:hover {
+    color: #006dba;
+    font-weight: bold;
+    text-decoration: none;
+}
+
+img {
+    border: 0px;
+}
+
+/*Do not specify a global h2 and h3
+    Since this changes filterPane and other headers.*/
+h1 {
+    color: #006dba;
+    font-weight: normal;
+    font-size: 17px;
+    margin: 0 0 .3em 0;
+}
+
+ul {
+    padding-left: 15px;
+}
+
+input, select, textarea {
+    background-color: #fcfcfc;
+    border: 1px solid #ccc;
+    font: 14px verdana, arial, helvetica, sans-serif;
+    margin: 2px 0;
+    padding: 2px 4px;
+}
+select {
+   padding: 2px 2px 2px 0;
+}
+textarea {
+    width: 450px;
+    height: 150px;
+    vertical-align: top;
+}
+
+input:focus, select:focus, textarea:focus {
+    border: 1px solid #b2d1ff;
+}
+
+.body {
+    padding: 20px 20px 20px 20px;
+    text-align: center;
+    /*border: 1px solid #ccc;*/
+}
+
+/* Ask IE to behave. Margin, width and height might be ignored by some FF versions. */
+input[type="checkbox"] {
+    background: transparent;
+    border: 0;
+    margin-bottom: -1px;
+}
+input[type="radio"] {
+    background: transparent;
+    border: 0;
+    margin-bottom: -1px;
+}
+
+/* Logout and Top Navigation Level */
+
+.appControl {
+    height: 2em;
+}
+.appControl a {
+    color: #666;
+}
+
+.logoutButton {
+    float: right;
+    padding: 0.3em 0px 0.3em 0;
+    font-size: 14px;
+    margin: 0 50px 0 0;
+    /*border: 1px solid #ccc;*/
+}
+
+.logoutButton:hover {
+    color: red;
+    padding: 0.5em 0px 0.1em 0;
+}
+
+/* ORIGINAL NAVIGATION MENU */
+
+.nav {
+    text-align: center;
+    background: url("../images/linkPanel_long.png") top no-repeat;
+    padding: 10px 0px 0px 0px;
+    width: 980px;
+    height: 40px;
+}
+
+.menuButton {
+    font-size: 14px;
+    padding: 0 5px;
+}
+.menuButton a {
+    color: #333;
+    padding: 14px 25px;
+}
+.menuButton a.home {
+    /*background: url(../images/skin/house.png) center left no-repeat;*/
+    color: #333;
+    /*padding: 25px;*/
+}
+.menuButton a.list {
+    /*background: url(../images/skin/database_table.png) center left no-repeat;*/
+    color: #333;
+    /*padding-left: 25px;*/
+}
+.menuButton a.create {
+    /*background: url(../images/skin/database_add.png) center left no-repeat;*/
+    color: #333;
+    /*padding-left: 25px;*/
+}
+
+/* MESSAGES AND ERRORS */
+
+.message {
+    background: #f3f8fc url(../images/skin/information.png) 8px 50% no-repeat;
+    border: 1px solid #b2d1ff;
+    color: #006dba;
+    margin: 10px 0 5px 0;
+    padding: 5px 5px 5px 0px
+}
+
+.message_error {
+    background: #fff3f3 url(../images/skin/exclamation.png) 8px 50% no-repeat;
+    border: 1px solid red;
+    color: #cc0000;
+    margin: 10px 0 5px 0;
+    padding: 5px 5px 5px 0px
+}
+
+div.errors {
+    background: #fff3f3;
+    border: 1px solid red;
+    color: #cc0000;
+    margin: 10px 0 5px 0;
+    padding: 5px 0 5px 0;
+}
+div.errors ul {
+    list-style: none;
+    padding: 0;
+}
+div.errors li {
+    background: url(../images/skin/exclamation.png) 8px 0% no-repeat;
+    line-height: 16px;
+    padding-left: 30px;
+}
+
+td.errors select {
+    background: #ffEbEb; /*Set select background since select borders cannot be styled in IE*/
+    border: 1px solid red;
+}
+td.errors input {
+    border: 1px solid red;
+}
+td.errors textarea {
+    border: 1px solid red;
+}
+
+input.time {
+    width:40px;
+}
+input.time.errors {
+    border: 1px solid red;
+}
+input.medium {
+    width:60px;
+}
+input.medium.errors {
+    border: 1px solid red;
+}
+input.description {
+    width:450px;
+}
+
+/* TABLES */
+
+table {
+    border: 1px solid #ccc;
+    width: 100%;
+}
+tr {
+    border: 0;
+}
+td, th {
+    font: 14px verdana, arial, helvetica, sans-serif;
+    line-height: 17px;
+    padding: 5px 6px;
+    text-align: left;
+    vertical-align: top;
+}
+tr.total {
+    background: #EDEDED;
+}
+tr.total td{
+    color: #555;
+    font-size: 14px;
+    font-weight: bold;
+}
+td.idColumn {
+    width: 25px;
+}
+th {
+    background: #fff url(../images/skin/shadow.jpg);
+    color: #555;
+    font-size: 14px;
+    font-weight: bold;
+    line-height: 17px;
+    padding: 2px 6px;
+}
+th a:link, th a:visited, th a:hover {
+    color: #333;
+    display: block;
+    font-size: 14px;
+    text-decoration: none;
+    width: 100%;
+}
+th.asc a, th.desc a {
+    background-position: right;
+    background-repeat: no-repeat;
+}
+th.asc a {
+    background-image: url(../images/skin/sorted_asc.gif);
+}
+th.desc a {
+    background-image: url(../images/skin/sorted_desc.gif);
+}
+
+.odd {
+    background: #f7f7f7;
+}
+.even {
+    background: #fff;
+}
+
+.clickableOdd {
+    background: #f7f7f7;
+    cursor: pointer;
+}
+.clickableEven {
+    background: #fff;
+    cursor: pointer;
+}
+.clickableEven td.notClickable {
+    cursor: default;
+}
+.clickableOdd td.notClickable {
+    cursor: default;
+}
+
+/* LIST */
+
+div.list {
+    clear:both;
+}
+.list table {
+    border-collapse: collapse;
+}
+.list th, .list td {
+    border-left: 1px solid #ddd;
+}
+.list th:hover, .list tr:hover {
+    background: #b2d1ff;
+}
+
+/* PAGINATION */
+
+.paginateButtons {
+    border-top: 0;
+    color: #666;
+    font-size: 14px;
+    overflow: hidden;
+    padding: 10px 3px;
+}
+.paginateButtons a {
+    background: #fff url(../images/skin/shadow.jpg) bottom repeat-x;
+    border: 1px solid #ccc;
+    border-color: #ccc #aaa #aaa #ccc;
+    color: #666;
+    margin: 0 3px;
+    padding: 2px 6px;
+}
+.paginateButtons span {
+    padding: 2px 3px;
+}
+
+.searchButtons {
+    background: #fff url(../images/skin/shadow.jpg) bottom repeat-x;
+    border: 1px solid #ccc;
+    border-color: #ccc #aaa #aaa #ccc;
+    margin: 0 0.5em;
+}
+.searchButtons a {
+    background: transparent url(../images/skin/database_search.png)  5px 50% no-repeat;
+    padding-left: 28px;
+    border: none;
+    margin: 0;
+}
+
+/* DIALOG */
+
+.dialog table {
+    padding: 5px 0;
+}
+
+.prop {
+    padding: 5px;
+}
+.prop .name {
+    text-align: left;
+    width: 15%;
+    white-space: nowrap;
+}
+.prop .value {
+    text-align: left;
+    width: 85%;
+}
+.prop .groupHeader {
+    text-decoration:underline;
+    text-align: left;
+    width: 15%;
+    white-space: nowrap;
+}
+.prop .groupName {
+    text-indent:15px;
+    text-align: left;
+    width: 15%;
+    white-space: nowrap;
+}
+
+/* ACTION BUTTONS */
+.generalButton {
+    background: #fff url(../images/skin/shadow.jpg) bottom repeat-x;
+    color: #444;
+    font-size: 14px;
+    font-weight: bold;
+    cursor: pointer;
+    margin-left: 5px;
+    overflow: hidden;
+    padding: 0.1em 0.4em 0.1em 0.4em;
+}
+
+.buttons {
+    background: #fff url(../images/skin/shadow.jpg) bottom repeat-x;
+    border: 1px solid #ccc;
+    color: #666;
+    font-size: 14px;
+    margin-top: -1px;
+    margin-bottom: 5px;
+    overflow: hidden;
+    padding: 3px;
+}
+.buttons input {
+    background: #fff;
+    border: 0;
+    color: #333;
+    cursor: pointer;
+    font-size: 14px;
+    font-weight: bold;
+    margin-left: 3px;
+    overflow: visible;
+    padding: 0px 6px;
+}
+.buttons input.delete {
+    background: transparent url(../images/skin/database_delete.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.trash {
+    background: transparent url(../images/skin/bin_closed.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.restore {
+    background: transparent url(../images/skin/bin_empty.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.cancel {
+    background: transparent url(../images/skin/cross.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.complete {
+    background: transparent url(../images/skin/tick.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.flag {
+    background: transparent url(../images/skin/flag_red.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.reopen {
+    background: transparent url(../images/skin/door_open.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.approve {
+    background: transparent url(../images/skin/cog_add.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.renegeApproval {
+    background: transparent url(../images/skin/cog_delete.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.edit {
+    background: transparent url(../images/skin/database_edit.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.save {
+    background: transparent url(../images/skin/database_save.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.add {
+    background: transparent url(../images/skin/database_add.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.search {
+    background: transparent url(../images/skin/database_search.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.link {
+    background: transparent url(../images/skin/database_link.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.go {
+    background: transparent url(../images/skin/database_go.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+.buttons input.table {
+    background: transparent url(../images/skin/database_table.png) 5px 50% no-repeat;
+    padding-left: 28px;
+}
+
+#bottom {
+  background: url("../images/bottomBg.png") no-repeat scroll center;
+  width: 1020px;
+  height: 100px;
+}
+
+/* Text Search */
+div.textSearchWrapper {
+    float: left;
+    width: 100%;
+}
+
+div.textSearchInput {
+    float: left;
+    width: 500px;
+    margin: 0 0 0 220px;
+    padding: 0;
+}
+
+div.textSearchSelect {
+    text-align: left;
+    padding: 5px 5px 5px 15px;
+}
+
+div.textSearchRightFloat {
+    float: right;
+    text-align: right;
+    margin: 0 10px 0 0;
+}
+
+/* Overlay Pane and filterPane plugin*/
+div.overlayPane {
+    position: absolute;
+    width:70%;
+    left: 50%;
+    margin-left: -36%;
+    top: 50%;
+    margin-top: -26%;
+    border: 2px solid #666666;
+    background-color: white;
+    padding: 5px;
+    z-index: 0;
+}
+
+.overlayTable {
+    width: 100%;
+}
+
+a.remove img {
+    border:none;
+}
+
+ /* Navigation Plugin Override */
+.navigation {
+    padding: 0px 0px 0px 50px;
+    list-style-type: none;
+    clear: both;
+    font-size: 14px;
+    /*overflow: hidden;*/ /* Clearing floats */
+}
+
+.navigation li {
+    float: left;
+    /*border: 0px*/
+    /* border: 1px solid #888; */
+     /*border-left-color: #bbb;*/  /* Highlight border-color */
+}
+
+.navigation li.navigation_first {
+     /*border-left-color: #888; */
+}
+
+.navigation li.navigation_active {
+     /*border-left-color: #555;*/  /* Highlight border-color of active item */
+}
+
+.navigation li a {
+    color: #666;
+    /* background-color: #aaa; */
+    padding: 0.3em 0.75em 0;
+    display: block;
+    text-decoration: none;
+}
+
+.navigation li a:hover {
+    color: red;
+    /* background-color: #999; */
+/*     font-weight: normal; */
+/*     font-size: 14px; */
+    padding: 0.5em 0.75em;
+    /*cursor: default;*/
+}
+
+.navigation li.navigation_active a {
+    /* background-color: #555; */
+/*    color: #fff;*/
+    color: #006dba;
+    /*color: black;*/
+    font-weight: bold;
+    font-size: 17px;
+    margin: 0 0 0 0;
+    /*cursor: default;*/
+}
+
+.navigation li.navigation_active a:hover {
+    color: #006dba;
+    font-weight: bold;
+    font-size: 17px;
+    padding: 0.3em 0.75em;
+    /*background-color: #555;*/
+}
+
+/* Sub navigation */
+.subnavigation {
+    /*padding: 0px 0px 0px 165px;*/
+    padding: 0px 0px 0px 105px;
+    list-style-type: none;
+    clear: both;
+    overflow: hidden; /* Clearing floats */
+}
+.subnavigation li {
+    float: left;
+    /* background-color: #555; */
+    padding: 0em 0.75em;
+    border-width: 0px 0;
+}
+.subnavigation li a {
+    color: #006dba;
+    font-weight: bold;
+    font-size: 17px;
+    display: block;
+    /*padding: 0px 0;*/
+    /* border-color: #555; */
+    border-style: solid;
+    border-width: 0px 0;
+    text-decoration: none;
+    /*margin: 0 0 0 0;*/
+    /*cursor: default;*/
+}
+
+.subnavigation li a:visited {
+    color: #006dba;
+}
+
+.subnavigation li a:hover {
+    /*color: red;*/
+    /*border-color: black;*/ 
+    border-width: 1px 0;
+}
+.subnavigation li.subnavigation_active a {
+    /*color: #e0e0e0; */
+    /*cursor: default;*/
+    /*border-color: #e0e0e0;*/
+    border-width: 1px 0;
+}
+
+/* Tree */
+
+div.static_tree {
+}
+div.static_tree ul {
+    list-style-type: none;
+    padding-left: 15px;
+}
+div.static_tree li {
+    background: url(../images/skin/ln.gif) 0px 0px no-repeat;
+    padding-left: 20px;
+    margin: 2px;
+}
+
+div.tree_button {
+    float: left;
+}
+div.tree_button a {
+}
+div.tree_button img {
+    padding: 0.3em 0.5em 0 0.3em;
+}
+div.tree_button img:hover {
+    padding: 0.5em 0.5em 0 0.3em;
+}
+
+div.tree {
+}
+div.tree li a{
+}
+div.tree ul {
+    list-style-type: none;
+    padding-left: 15px;
+}
+div.tree li {
+    background: url(../images/skin/ln.gif) 0px 0px no-repeat;
+    padding-left: 10px;
+    margin: 2px;
+}
+div.pane_close {
+    position: absolute;
+    right: 5px;
+    padding: 5px;
+}
+
+/* CheckBoxList Tag Lib */
+
+.CheckBoxList {
+    height: 300px;
+    overflow: auto;
+    overflow-x: hidden;
+    width: 400px;
+    border: 1px solid #ccc;
+    list-style-type: none;
+    margin: 0;
+    padding: 0px;
+}
+.CheckBoxList li {
+    padding: 5px;
+}
Index: branches/features/taskProcedureRework/web-app/css/tabviewCustom.css
===================================================================
--- branches/features/taskProcedureRework/web-app/css/tabviewCustom.css	(revision 753)
+++ branches/features/taskProcedureRework/web-app/css/tabviewCustom.css	(revision 753)
@@ -0,0 +1,317 @@
+/*
+Copyright (c) 2008, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.6.0
+*/
+.yui-navset .yui-nav li,
+.yui-navset .yui-navset-top .yui-nav li,.yui-navset .yui-navset-bottom .yui-nav li{
+    margin:0 0.5em 0 0;
+}
+
+.yui-navset-left .yui-nav li,
+.yui-navset-right .yui-nav li{
+    margin:0 0 0.5em;
+}
+
+.yui-navset .yui-content .yui-hidden{
+    display:none;
+}
+
+.yui-navset .yui-navset-left .yui-nav,
+.yui-navset .yui-navset-right .yui-nav,
+.yui-navset-left .yui-nav,
+.yui-navset-right .yui-nav{
+    width:6em;
+}
+
+.yui-navset-top .yui-nav,
+.yui-navset-bottom .yui-nav{
+    width:auto;
+}
+
+.yui-navset .yui-navset-left,
+.yui-navset-left{
+    padding:0 0 0 6em;
+}
+
+.yui-navset-right{
+    padding:0 6em 0 0;
+}
+
+.yui-navset-top,.yui-navset-bottom{
+    padding:auto;
+}
+
+.yui-nav,
+.yui-nav li{
+    margin:0;
+    padding:0;
+    list-style:none;
+}
+
+.yui-navset li em{
+    font-style:normal;
+}
+
+.yui-navset{
+    position:relative;
+    zoom:1;
+}
+
+.yui-navset .yui-content{
+    zoom:1;
+}
+
+.yui-navset .yui-nav li,
+.yui-navset .yui-navset-top .yui-nav li,
+.yui-navset .yui-navset-bottom .yui-nav li{
+    display:inline-block;
+    display:-moz-inline-stack;
+    display:inline;
+    vertical-align:bottom;
+    cursor:pointer;zoom:1;
+}
+
+.yui-navset-left .yui-nav li,
+.yui-navset-right .yui-nav li{
+    display:block;
+}
+
+.yui-navset .yui-nav a{
+    position:relative;
+}
+
+.yui-navset .yui-nav li a,
+.yui-navset-top .yui-nav li a,
+.yui-navset-bottom .yui-nav li a{
+    display:block;
+    display:inline-block;
+    vertical-align:bottom;
+    zoom:1;
+}
+
+.yui-navset-left .yui-nav li a,
+.yui-navset-right .yui-nav li a{
+    display:block;
+}
+
+.yui-navset-bottom .yui-nav li a{
+    vertical-align:text-top;
+}
+
+.yui-navset .yui-nav li a em,
+.yui-navset-top .yui-nav li a em,
+.yui-navset-bottom .yui-nav li a em{
+    display:block;
+}
+
+.yui-navset .yui-navset-left .yui-nav,
+.yui-navset .yui-navset-right .yui-nav,
+.yui-navset-left .yui-nav,
+.yui-navset-right .yui-nav{
+    position:absolute;
+    z-index:1;
+}
+
+.yui-navset-top .yui-nav,
+.yui-navset-bottom .yui-nav{
+    position:static;
+}
+
+.yui-navset .yui-navset-left .yui-nav,
+.yui-navset-left .yui-nav{
+    left:0;
+    right:auto;
+}
+
+.yui-navset .yui-navset-right .yui-nav,
+.yui-navset-right .yui-nav{
+    right:0;
+    left:auto;
+}
+
+.yui-skin-sam .yui-navset .yui-nav,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-nav{/*Nav underl line*/
+    border:solid #2647a0;
+    border-width:0 0 5px;
+    Xposition:relative;
+    zoom:1;
+}
+
+.yui-skin-sam .yui-navset .yui-nav li,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-nav li{
+    margin:0 0.16em 0 0;
+    padding:1px 0 0;
+    zoom:1;
+}
+
+.yui-skin-sam .yui-navset .yui-nav .selected,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-nav .selected{
+    margin:0 0.16em -1px 0;
+}
+
+.yui-skin-sam .yui-navset .yui-nav a,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a{/* tab background */
+/*    background:#d8d8d8 url("../images/skin/sprite.png") repeat-x; */
+    background:#d8d8d8;
+    border:solid #a3a3a3;
+    border-width:0 1px;
+    color:#000;
+    position:relative;
+    text-decoration:none;
+}
+
+.yui-skin-sam .yui-navset .yui-nav a em,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a em{
+    border:solid #a3a3a3;
+    border-width:1px 0 0;
+    cursor:hand;
+    padding:0.25em .75em;
+    left:0;
+    right:0;
+    bottom:0;
+    top:-1px;
+    position:relative;
+}
+
+.yui-skin-sam .yui-navset .yui-nav .selected a,
+.yui-skin-sam .yui-navset .yui-nav .selected a:focus,
+.yui-skin-sam .yui-navset .yui-nav .selected a:hover{/*selected tab background*/
+/*     background:#2647a0 url("../images/skin/sprite.png") repeat-x left -1400px;  */
+    background:#2647a0;
+    color:#fff;
+}
+
+.yui-skin-sam .yui-navset .yui-nav a:hover,
+.yui-skin-sam .yui-navset .yui-nav a:focus{/*hover background*/
+/*     background:#bfdaff url("../images/skin/sprite.png") repeat-x left -1300px;  */
+    background:#bfdaff;
+    outline:0;
+}
+
+.yui-skin-sam .yui-navset .yui-nav .selected a em{
+    padding:0.35em 0.75em;
+}
+
+.yui-skin-sam .yui-navset .yui-nav .selected a,
+.yui-skin-sam .yui-navset .yui-nav .selected a em{
+    border-color:#243356;
+}
+
+.yui-skin-sam .yui-navset .yui-content{/* content background color */
+    background: #FFFFE1;
+/*   background: url("../images/Contentbg.png") repeat-y scroll center; */
+}
+
+.yui-skin-sam .yui-navset .yui-content,
+.yui-skin-sam .yui-navset .yui-navset-top .yui-content{
+    border:0px solid #808080;
+    border-top-color:#243356;
+    padding:0.25em 0.5em;
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav,
+.yui-skin-sam .yui-navset .yui-navset-left .yui-nav,
+.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,
+.yui-skin-sam .yui-navset-right .yui-nav{
+    border-width:0 5px 0 0;
+    Xposition:absolute;
+    top:0;
+    bottom:0;
+}
+
+.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,
+.yui-skin-sam .yui-navset-right .yui-nav{
+    border-width:0 0 0 5px;
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav li,
+.yui-skin-sam .yui-navset .yui-navset-left .yui-nav li,
+.yui-skin-sam .yui-navset-right .yui-nav li{
+    margin:0 0 0.16em;
+    padding:0 0 0 1px;
+}
+
+.yui-skin-sam .yui-navset-right .yui-nav li{
+    padding:0 1px 0 0;
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav .selected,
+.yui-skin-sam .yui-navset .yui-navset-left .yui-nav .selected{
+    margin:0 -1px 0.16em 0;
+}
+
+.yui-skin-sam .yui-navset-right .yui-nav .selected{
+    margin:0 0 0.16em -1px;
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav a,
+.yui-skin-sam .yui-navset-right .yui-nav a{
+    border-width:1px 0;
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav a em,
+.yui-skin-sam .yui-navset .yui-navset-left .yui-nav a em,
+.yui-skin-sam .yui-navset-right .yui-nav a em{
+    border-width:0 0 0 1px;
+    padding:0.2em .75em;
+    top:auto;
+    left:-1px;
+}
+
+.yui-skin-sam .yui-navset-right .yui-nav a em{
+    border-width:0 1px 0 0;
+    left:auto;
+    right:-1px;
+}
+
+.yui-skin-sam .yui-navset-left .yui-nav a,
+.yui-skin-sam .yui-navset-left .yui-nav .selected a,
+.yui-skin-sam .yui-navset-left .yui-nav a:hover,
+.yui-skin-sam .yui-navset-right .yui-nav a,
+.yui-skin-sam .yui-navset-right .yui-nav .selected a,
+.yui-skin-sam .yui-navset-right .yui-nav a:hover,
+.yui-skin-sam .yui-navset-bottom .yui-nav a,
+.yui-skin-sam .yui-navset-bottom .yui-nav .selected a,
+.yui-skin-sam .yui-navset-bottom .yui-nav a:hover{
+    background-image:none;
+}
+
+.yui-skin-sam .yui-navset-left .yui-content{
+    border:1px solid #808080;
+    border-left-color:#243356;
+}
+
+.yui-skin-sam .yui-navset-bottom .yui-nav,
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav{
+    border-width:5px 0 0;
+}
+
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav .selected,
+.yui-skin-sam .yui-navset-bottom .yui-nav .selected{
+    margin:-1px 0.16em 0 0;
+}
+
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav li,
+.yui-skin-sam .yui-navset-bottom .yui-nav li{
+    padding:0 0 1px 0;
+    vertical-align:top;
+}
+
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav li a,
+.yui-skin-sam .yui-navset-bottom .yui-nav li a{
+}
+
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav a em,
+.yui-skin-sam .yui-navset-bottom .yui-nav a em{
+    border-width:0 0 1px;
+    top:auto;
+    bottom:-1px;
+}
+
+.yui-skin-sam .yui-navset-bottom .yui-content,
+.yui-skin-sam .yui-navset .yui-navset-bottom .yui-content{
+    border:1px solid #808080;
+    border-bottom-color:#243356;
+}
Index: branches/features/taskProcedureRework/web-app/js/application.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/application.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/application.js	(revision 753)
@@ -0,0 +1,13 @@
+var Ajax;
+if (Ajax && (Ajax != null)) {
+    Ajax.Responders.register({
+    onCreate: function() {
+        if($('spinner') && Ajax.activeRequestCount>0)
+        Effect.Appear('spinner',{duration:0.5,queue:'end'});
+    },
+    onComplete: function() {
+        if($('spinner') && Ajax.activeRequestCount==0)
+        Effect.Fade('spinner',{duration:0.5,queue:'end'});
+    }
+    });
+}
Index: branches/features/taskProcedureRework/web-app/js/assetTree.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/assetTree.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/assetTree.js	(revision 753)
@@ -0,0 +1,34 @@
+
+function showAssetTreePane(paneDivId, loadingImg, url) {
+
+    Effect.Appear(paneDivId,{duration:0.4});
+
+    // Disabled since pulsing effect blocks other javascript till complete.
+    // The effect may be stopped with e.cancel() but we will use the default Grails spinner for now.
+    // def e = new Effect.Pulsate($(loadingImg), { pulses: 200, duration: 133 });
+
+    new Ajax.Updater({ success: paneDivId }, url, {asynchronous:true,evalScripts:true});
+}
+
+function hideAssetTreePane(paneDivId, tableDivId, saveUrl) {
+
+    // Collect the visible branch div's first.
+    var visibleDivs = $(tableDivId).select('div').findAll(function(el) { return el.visible(); })
+    var params = "assetTreeVisibleBranches=";
+
+    // Hide the pane.
+    $(paneDivId).toggle();
+
+    // Add the id of each visible div to params.
+    visibleDivs.each(function(it) {
+        params += it.identify();
+        params += ","
+    });
+
+    // Remove the trailing comma.
+    params = params.slice(0,params.length-1);
+
+    // Post the id's of all visible branch div's.
+    // asynchronous: false is against the prototype recommendations but appears to be needed in this case.
+    new Ajax.Request(saveUrl, {parameters: params, asynchronous: false});
+}
Index: branches/features/taskProcedureRework/web-app/js/jsUtil.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/jsUtil.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/jsUtil.js	(revision 753)
@@ -0,0 +1,120 @@
+
+function toggleUtil(id) {
+    $(id).toggle();
+}
+
+function toggleWithImgUtil(id, imageId, openImgUrl, closedImgUrl) {
+
+    $(id).toggle();
+
+    if( $(id).visible() ) {
+        $(imageId).src= openImgUrl;
+    }
+    else {
+        $(imageId).src= closedImgUrl;
+    }
+}
+
+function showUtil(id) {
+    Effect.Appear(id,{duration:0.2,queue:'end'});
+}
+
+function hideUtil(id) {
+    Effect.Fade(id,{duration:0.2,queue:'end'});
+}
+
+function toggleWithEffectUtil(id) {
+    if( $(id).visible() ) {
+        Effect.Fade(id,{duration:0.4,queue:'end'});
+    }
+    else {
+        Effect.Appear(id,{duration:0.4,queue:'end'});
+    }
+}
+
+function toggleWithImgAndEffectUtil(id, imageId, openImgUrl, closedImgUrl) {
+
+    if( $(id).visible() ) {
+        Effect.Fade(id,{duration:0.4,queue:'end'});
+        $(imageId).src= closedImgUrl;
+    }
+    else {
+        Effect.Appear(id,{duration:0.4,queue:'end'});
+        $(imageId).src= openImgUrl;
+    }
+}
+
+function textAreaScrollBottom(id) {
+    $(id).scrollTop = $(id).scrollHeight;
+}
+
+function focusUtil(id) {
+    $(id).focus();
+}
+
+function enableUtil(id) {
+    $(id).disabled = false;
+}
+
+function disableUtil(id) {
+    $(id).disabled = true;
+}
+
+// Looping in reverse is apparently more efficient.
+function containsUtil(val, array) {
+    var i = array.length;
+    while (i--) {
+        if (array[i] == val) {
+            return true;
+        }
+    }
+    return false;
+}
+
+function toggleArrayUtil(idArray) {
+    var i = idArray.length;
+    while (i--) {
+        toggleUtil(idArray[i]);
+    }
+}
+
+// Loops forwards.
+function showArrayUtil(idArray) {
+    var len = idArray.length
+    var i=0;
+    for (i=0; i < len; i++) {
+        Effect.Appear(idArray[i],{duration:0.05,queue:'end'});
+    }
+}
+
+// Loops backwards.
+function hideArrayUtil(idArray) {
+    var i = idArray.length;
+    while (i--) {
+        Effect.Fade(idArray[i],{duration:0.05,queue:'end'});
+    }
+}
+
+function disableArrayUtil(idArray) {
+    var i = idArray.length;
+    while (i--) {
+        disableUtil(idArray[i]);
+    }
+}
+
+function enableArrayUtil(idArray) {
+    var i = idArray.length;
+    while (i--) {
+        enableUtil(idArray[i]);
+    }
+}
+
+function toggleIfArrayContainsValueUtil(toggleIds, val, array) {
+    if(containsUtil(val, array)) {
+        //Effect.multiple(toggleIds, Effect.Appear, {duration:0.4,queue:'end'}); // A little slow, will not go bellow 0.1 per item.
+        showArrayUtil(toggleIds);
+    }
+    else {
+        hideArrayUtil(toggleIds);
+    }
+}
Index: branches/features/taskProcedureRework/web-app/js/lightbox.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/lightbox.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/lightbox.js	(revision 753)
@@ -0,0 +1,731 @@
+//
+//	Lightbox version 3.0.0
+//	by Lokesh Dhakar - http://www.huddletogether.com
+//	04/03/2008
+//
+//	For more information on this script, visit:
+//	http://huddletogether.com/projects/lightbox2/
+//
+//	Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
+//
+//	Credit also due to those who have helped, inspired, and made their code available to the public.
+//	Including: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.org), Thomas Fuchs(mir.aculo.us), and others.
+//
+
+/*
+
+  Table of Contents
+  -----------------
+
+  Extending Built-in Objects
+  - Object.extend(Element)
+  - Array.prototype.removeDuplicates()
+
+  Lightbox Class Declaration
+  - block()
+  - onload()
+  - updateImageList()
+  
+  Miscellaneous Functions
+  - getPageScroll()
+  - getPageSize()
+  - showSelectBoxes()
+  - hideSelectBoxes()
+  - showObjects()
+  - hideObjects()
+  - pause()
+
+*/
+
+//	Additional methods for Element added by SU, Couloir
+//	- further additions by Lokesh Dhakar (huddletogether.com)
+Object.extend(Element, {
+  setWidth: function (element, width) {
+    $(element).style.width = width + "px";
+  },
+  setHeight: function (element, height) {
+    $(element).style.height = height + "px";
+  },
+  setTop: function (element, top) {
+    $(element).style.top = top + "px";
+  },
+  setLeft: function (element, left) {
+    $(element).style.left = left + "px";
+  },
+  setSrc: function (element, src) {
+    $(element).src = src;
+  },
+  setInnerHTML: function (element, content) {
+    $(element).innerHTML = content;
+  }
+});
+
+//	Extending built-in Array object
+//	- array.removeDuplicates()
+Array.prototype.removeDuplicates = function () {
+  for (i = 1; i < this.length; i++) {
+    if (this[i][0] == this[i - 1][0]) { this.splice(i, 1); }
+  }
+}
+
+//	Lightbox Class Declaration
+//	- block()
+//  - onload()
+//  - updateImageList()
+
+//	Structuring of code inspired by Scott Upton (http://www.uptonic.com/)
+
+var Lightbox = {
+
+  onload: function (event) {
+
+    // preload image.
+    loadingImage = new Image();
+    loadingImage.src =  Lightbox._imagePath + "loading.gif";
+
+    var options = { 'minWidth' : 650};
+    return Lightbox._create(options);
+  },
+
+  // Fades to overlay and runs an animated loading gif (e.g after form submit)
+  loading: function(options) {
+    if (!document.getElementsByTagName) { return true; }
+
+     Lightbox._options(options);
+
+     var buttons = document.getElementsByClassName("buttons");
+     buttons[0].style.visibility = "hidden";
+
+    var parent = document.getElementsByTagName("body").item(0);
+    var overlay = Lightbox._createElement("div", "overlay", "none", null, null, function (event) {} );
+    parent.appendChild(overlay);
+
+    var pageSize = getPageSize();
+    Element.setWidth('overlay', pageSize[0]);
+    Element.setHeight('overlay', pageSize[1]);
+
+    if (Lightbox._animate) {
+      new Effect.Appear('overlay', { duration: Lightbox._overlayBlockDuration, from: 0.0, to: Lightbox._blockOpacity });
+    }
+    else {
+      Element.setOpacity('overlay', Lightbox._opacity);
+    }
+
+    if (Lightbox._animate) {
+        var loading = Lightbox._createElement("div", 'loading');
+        parent.appendChild(loading);
+
+        // document.all should be detected in IE and Opera, workaround for IE gif freezing.
+        if(document.all) {
+            new Effect.Pulsate(loading, { pulses: 800, duration: 532 });
+        }
+        else {
+            Element.show('loading');
+        }
+    }
+
+  },
+
+
+  // Blocks the page (after form submit)
+  block: function(message, options) {
+    if (!document.getElementsByTagName) { return true; }
+
+    Lightbox._options(options);
+    
+    var parent = document.getElementsByTagName("body").item(0);
+    var overlay = Lightbox._createElement("div", "overlay", "none", null, null, function (event) {} );
+    parent.appendChild(overlay);
+        
+    // The rest of this code inserts html at the bottom of the page that looks similar to this:
+    //
+    // <div id="lightbox">
+    //   <div id="outerImageContainer">
+    //     <div id="imageContainer">
+    //       <div id="loading"></div>
+    //       <div id="imageDataContainer"> message </div>
+    //     </div>
+    //   </div>
+    // </div>
+
+    var lightbox = Lightbox._createElement("div", "lightbox", "none");
+    parent.appendChild(lightbox);
+
+    var outerImageContainer = Lightbox._createElement("div", "outerImageContainer");
+    lightbox.appendChild(outerImageContainer);
+
+    var imageContainer = Lightbox._createElement("div", 'imageContainer');
+    outerImageContainer.appendChild(imageContainer);
+
+	imageContainer.appendChild(Lightbox._createElement("div", 'loading'));
+    imageDataContainer = Lightbox._createElement("div", 'imageDataContainer');
+    imageContainer.appendChild(imageDataContainer);
+    imageDataContainer.appendChild(document.createTextNode(message));
+
+    hideSelectBoxes();
+    hideObjects();
+    var pageSize = getPageSize();
+    Element.setWidth('overlay', pageSize[0]);
+    Element.setHeight('overlay', pageSize[1]);
+    Element.setOpacity('overlay', Lightbox._blockOpacity);
+    Element.show('overlay');
+    Element.setTop('lightbox', Number(getPageScroll()[1] + (getPageSize()[3] / 15)).toFixed());
+    Element.show('lightbox');
+    Element.show('loading');
+    return true;
+  },
+  
+  // Loops through anchor tags looking for 'lightbox' references and applies onclick
+  // events to appropriate links. You can rerun after dynamically adding images w/ajax.
+  updateImageList: function () {
+    if (!document.getElementsByTagName) { return; }
+
+    // loop through all anchor tags
+    var anchors = document.getElementsByTagName('a');
+    for (var i = 0, l = anchors.length; i < l; i++) {
+      var anchor = anchors[i];
+      // use the string.match() method to catch 'lightbox' references in the rel attribute
+      var relAttribute = String(anchor.getAttribute('rel'));
+      if (anchor.getAttribute('href') && (relAttribute.toLowerCase().match('lightbox'))) {
+        anchor.onclick = function () { return Lightbox._start(this); };
+      }
+    }
+
+    // loop through all area tags
+    // todo: combine anchor & area tag loops
+    var areas = document.getElementsByTagName('area');
+    for (var i = 0, l = areas.length; i < l; i++) {
+      var area = areas[i];
+      // use the string.match() method to catch 'lightbox' references in the rel attribute
+      var relAttribute = String(area.getAttribute('rel'));
+      if (area.getAttribute('href') && (relAttribute.toLowerCase().match('lightbox'))) {
+        Area.onclick = function () { return Lightbox.start(this); }
+      }
+    }
+  },
+
+  // Loops through anchor tags looking for 'lightbox' references and applies onclick events 
+  // to appropriate links. The 2nd section of the function inserts html at the bottom of the 
+  // page which is used to display the shadow overlay and the image container.
+  _create: function(options) {
+    if (!document.getElementsByTagName) return;
+
+    Lightbox._options(options);
+
+    var parent = document.getElementsByTagName("body").item(0);
+    var overlay = Lightbox._createElement("div", "overlay", "none", null, null, Lightbox._overlayEnd);
+    parent.appendChild(overlay);
+
+    Lightbox.updateImageList();
+        
+    // The rest of this code inserts html at the bottom of the page that looks similar to this:
+    //
+    // <div id="lightbox">
+    //   <div id="outerImageContainer">
+    //     <div id="imageContainer">
+    //       <img id="lightboxImage" />
+    //       <div id="hoverNav">
+    //         <a href="#" id="prevLink"></a>
+    //         <a href="#" id="nextLink"></a>
+    //       </div>
+    //       <div id="loading"></div>
+    //     </div>
+    //   </div>
+    //   <div id="imageDataContainer">
+    //     <div id="imageData">
+    //       <div id="imageDetails">
+    //         <span id="caption"></span>
+    //         <span id="numberDisplay"></span>
+    //       </div>
+    //       <div id="bottomNav">
+    //         <img id="bottomNavPrev" />
+    //         <img id="bottomNavNext" />
+    //         <img id="bottomNavClose" />
+    //       </div>
+    //     </div>
+    //   </div>
+    // </div>
+
+    var lightbox = Lightbox._createElement("div", "lightbox", "none", null, null, Lightbox._overlayEnd);
+    parent.appendChild(lightbox);
+
+    var outerImageContainer = Lightbox._createElement("div", "outerImageContainer");
+    lightbox.appendChild(outerImageContainer);
+
+    // When Lightbox starts it will resize itself from 250 by 250 to the current image dimension.
+    // If animations are turned off, it will be hidden as to prevent a flicker of a
+    // white 250 by 250 box.
+    if (Lightbox._animate) {
+      Element.setWidth('outerImageContainer', 250);
+      Element.setHeight('outerImageContainer', 250);
+    }
+    else {
+      Element.setWidth('outerImageContainer', 1);
+      Element.setHeight('outerImageContainer', 1);
+    }
+
+    var imageContainer = Lightbox._createElement("div", 'imageContainer');
+    outerImageContainer.appendChild(imageContainer);
+    imageContainer.appendChild(Lightbox._createElement("img", 'lightboxImage'));
+
+    var hoverNav = Lightbox._createElement("div", 'hoverNav');
+    imageContainer.appendChild(hoverNav);
+
+    hoverNav.appendChild(Lightbox._createElement("a", 'prevLink', null, null, '#'));
+    hoverNav.appendChild(Lightbox._createElement("a", 'nextLink', null, null, '#'));
+
+    imageContainer.appendChild(Lightbox._createElement("div", 'loading', null, null, null, Lightbox._end));
+
+    imageDataContainer = Lightbox._createElement("div", 'imageDataContainer');
+    lightbox.appendChild(imageDataContainer);
+
+    imageData = Lightbox._createElement("div", 'imageData');
+    imageDataContainer.appendChild(imageData);
+
+    var imageDetails = Lightbox._createElement("div", 'imageDetails');
+    imageData.appendChild(imageDetails);
+
+    imageDetails.appendChild(Lightbox._createElement("span", 'caption'));
+    imageDetails.appendChild(Lightbox._createElement("span", 'numberDisplay'));
+
+    bottomNav = Lightbox._createElement("div", 'bottomNav');
+    imageData.appendChild(bottomNav);
+
+    bottomNav.appendChild(Lightbox._createElement("img", 'bottomNavPrev',  null, Lightbox._imagePath + "miniprev.jpg",   null, Lightbox._prevImage));
+    bottomNav.appendChild(Lightbox._createElement("img", 'bottomNavNext',  null, Lightbox._imagePath + "mininext.jpg",   null, Lightbox._nextImage));
+    bottomNav.appendChild(Lightbox._createElement("img", 'bottomNavClose', null, Lightbox._imagePath + "closelabel.gif", null, Lightbox._end));
+  },
+
+  _createElement: function (type, id, display, src, href, onclick) {
+    elem = document.createElement(type);
+    if (id)      { elem.setAttribute('id', id); }
+    if (display) { elem.style.display = display; }
+    if (src)     { elem.setAttribute('src', src); }
+    if (href)    { elem.setAttribute('href', href); }
+	if (onclick) { elem.onclick = onclick; }
+    return elem;
+  },
+
+  _options: function(options) {
+    if (options) {
+      var option = options['borderSize'];
+      if (option) { Lightbox._borderSize = option; }
+      option = options['overlayDuration'];
+      if (option) { Lightbox._overlayDuration = option; }
+      option = options['resizeDuration'];
+      if (option) { Lightbox._resizeDuration = option; }
+      option = options['minWidth'];
+      if (option) { Lightbox._minWidth = option; }
+      option = options['imagePath'];
+      if (option) { Lightbox._imagePath = option; }
+      option = options['opacity'];
+      if (option) { Lightbox._opacity = option; }
+      option = options['blockOpacity'];
+      if (option) { Lightbox._blockOpacity = option; }
+      option = options['animate'];
+      if (option) { Lightbox._animate = option; }
+      option = options['text'];
+      if (option) { Lightbox._text = option; }
+    }    
+  },
+
+  // Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
+  _start: function (imageLink) {
+    hideSelectBoxes();
+    hideObjects();
+
+    // stretch overlay to fill page and fade in
+    var pageSize = getPageSize();
+    Element.setWidth('overlay', pageSize[0]);
+    Element.setHeight('overlay', pageSize[1]);
+
+    if (Lightbox._animate) {
+      new Effect.Appear('overlay', { duration: Lightbox._overlayDuration, from: 0.0, to: Lightbox._opacity });
+    }
+    else {
+      Element.setOpacity('overlay', Lightbox._opacity);
+    }
+
+    Lightbox._activeImage = 0;
+    Lightbox._imageArray = [];
+    var imageNum = 0;
+    if ((imageLink.getAttribute('rel') == 'lightbox')) { // if image is NOT part of a set..
+	  Lightbox._imageArray.push(new Array(imageLink.getAttribute('href'), imageLink.getAttribute('title')));
+    }
+    else { // if image is part of a set..
+      // loop through anchors, find other images in set, and add them to imageArray
+      var rel = imageLink.getAttribute('rel');
+      var anchors = document.getElementsByTagName(imageLink.tagName);
+      for (var i = 0, l = anchors.length; i < l; i++) {
+        var anchor = anchors[i];
+        if (anchor.getAttribute('href') && (anchor.getAttribute('rel') == rel)) {
+          Lightbox._imageArray.push(new Array(anchor.getAttribute('href'), anchor.getAttribute('title')));
+        }
+      }
+      Lightbox._imageArray.removeDuplicates();
+      var href = imageLink.getAttribute('href');
+      while (Lightbox._imageArray[imageNum][0] != href) { imageNum++; }
+    }
+
+    // calculate top offset for the lightbox and display
+    var pageScroll = getPageScroll();
+    Element.setTop('lightbox', Number(pageScroll[1] + (pageSize[3] / 10)).toFixed());
+    Element.setLeft('lightbox', Number(pageScroll[0]).toFixed());
+    Element.show('lightbox');
+    Lightbox._changeImage(imageNum);
+    return false;
+  },
+
+  _overlayEnd: function (event) {
+    if (!event) { event = window.event; }
+    var id = Event.element(event).id;
+    if (id == 'overlay' || id == 'lightbox') { return Lightbox._end(); }
+    return true;
+  },
+
+  _end: function (event) {
+    Lightbox._disableKeyboardNav();
+    Element.hide('lightbox');
+    if (Lightbox._animate) {
+      new Effect.Fade('overlay', { duration: Lightbox._overlayDuration });
+    } 
+    else {
+      Element.hide('overlay');
+    }
+    showSelectBoxes();
+    showObjects();
+    return false;
+  },
+
+  _hasNext: function () {
+    return Lightbox._activeImage < (Lightbox._imageArray.length - 1);
+  },
+
+  _nextImage: function () {
+    Lightbox._changeImage(Lightbox._activeImage + 1);
+    return false;
+  },
+
+  _hasPrev: function () {
+    return Lightbox._activeImage > 0;
+  },
+
+  _prevImage: function () {
+    Lightbox._changeImage(Lightbox._activeImage - 1);
+    return false;
+  },
+
+  // Hide most elements and preload image in preparation for resizing image container.
+  _changeImage: function (imageNum) {
+    Lightbox._activeImage = imageNum;
+    
+    // hide elements during transition
+    if (Lightbox._animate) { Element.show('loading'); }
+    Element.hide('lightboxImage');
+    Element.hide('hoverNav');
+    Element.hide('prevLink');
+    Element.hide('nextLink');
+    Element.hide('bottomNavPrev');
+    Element.hide('bottomNavNext');
+    Element.hide('imageDataContainer');
+    Element.hide('caption');
+    Element.hide('numberDisplay');
+
+    // once image is preloaded, resize image container
+    Lightbox._preloader = new Image();
+    Lightbox._preloader.onload = function () {
+      Element.setSrc('lightboxImage', Lightbox._imageArray[imageNum][0]);
+      Lightbox._preloader.onload = function () { }; // clear onLoad, IE behaves irratically with animated gifs otherwise 
+      Lightbox._resizeImageContainer(Lightbox._preloader.width, Lightbox._preloader.height);
+    };
+    Lightbox._preloader.src = Lightbox._imageArray[imageNum][0];
+  },
+
+  _resizeImageContainer: function (imgWidth, imgHeight) {
+    var borders = Lightbox._borderSize * 2;
+    
+    // keep to a minimum width, if specified
+    if (Lightbox._minWidth > 0 && (imgWidth + borders) < Lightbox._minWidth) {
+      imgWidth = Lightbox._minWidth - borders;
+    }
+
+    // get current height and width
+    var widthCurrent = Element.getWidth('outerImageContainer');
+    var heightCurrent = Element.getHeight('outerImageContainer');
+
+    // get new width and height
+    var widthNew = imgWidth + borders;
+    var heightNew = imgHeight + borders;
+
+    // scalars based on change from old to new
+    var xScale = (widthNew / widthCurrent) * 100;
+    var yScale = (heightNew / heightCurrent) * 100;
+    
+    // calculate size difference between new and old image, and resize if necessary
+    var widthDiff = widthCurrent - widthNew;
+	var heightDiff = heightCurrent - heightNew;
+    if (heightDiff != 0) {
+      new Effect.Scale('outerImageContainer', yScale, { scaleX: false, duration: Lightbox._resizeDuration, queue: 'front' });
+    }
+	if (widthDiff != 0) {
+	  new Effect.Scale('outerImageContainer', xScale, { scaleY: false, duration: Lightbox._resizeDuration, delay: Lightbox._resizeDuration });
+	}
+
+    // if new and old image are same size and no scaling transition is necessary,
+    // do a quick pause to prevent image flicker.
+    if ((heightDiff == 0) && (widthDiff == 0)) {
+      if (navigator.appVersion.indexOf("MSIE") != -1) { pause(250); } else { pause(100); }
+    }
+
+    Element.setHeight('prevLink', imgHeight);
+    Element.setHeight('nextLink', imgHeight);
+    Element.setWidth('imageDataContainer', widthNew);
+    Lightbox._showImage();
+  },
+
+  // Display image.
+  _showImage: function () {
+    Element.hide('loading');
+    new Effect.Appear('lightboxImage', { duration: Lightbox._resizeDuration, queue: 'end', afterFinish: Lightbox._updateDetails });
+	Lightbox._preloadNeighborImages();
+  },
+
+  // Display caption, image number, and bottom nav.
+  _updateDetails: function () {
+    // if caption is not null
+	var caption = Lightbox._imageArray[Lightbox._activeImage][1];
+    if (caption) {
+      Element.show('caption');
+      Element.setInnerHTML('caption', caption);
+    }
+		
+    // if image is part of set display 'Image x of x'
+    if (Lightbox._imageArray.length > 1) {
+      Element.show('numberDisplay');
+      var text = Lightbox._text.replace("*", (Lightbox._activeImage + 1));
+      text = text.replace("*", Lightbox._imageArray.length);
+      Element.setInnerHTML('numberDisplay', text);
+    } 
+
+    if (Lightbox._hasPrev()) { Element.show('bottomNavPrev'); }	
+    if (Lightbox._hasNext()) { Element.show('bottomNavNext'); }
+
+	new Effect.Parallel(
+	  [ new Effect.SlideDown('imageDataContainer', { sync: true, duration: Lightbox._resizeDuration }),
+        new Effect.Appear('imageDataContainer', { sync: true, duration: Lightbox._resizeDuration }) ],
+      { duration: Lightbox._resizeDuration, afterFinish: Lightbox._updateNav });
+  },
+
+  // Display appropriate previous and next hover navigation.
+  _updateNav: function () {
+    $('imageDataContainer').style.overflow = 'auto'; // css float fix
+
+    Element.setHeight('overlay', getPageSize()[1]);
+
+    Element.show('hoverNav');
+
+    // if not first image in set, display prev image button
+    if (Lightbox._hasPrev()) {
+      document.getElementById('prevLink').onclick = Lightbox._prevImage;
+      Element.show('prevLink');
+      }
+
+    // if not last image in set, display next image button
+    if (Lightbox._hasNext()) {
+      document.getElementById('nextLink').onclick = Lightbox._nextImage;
+      Element.show('nextLink');
+    }
+   Lightbox._enableKeyboardNav();
+  },
+
+  _enableKeyboardNav: function () {
+    document.onkeydown = Lightbox._keyboardAction;
+  },
+
+  _disableKeyboardNav: function () {
+    document.onkeydown = '';
+  },
+
+  _keyboardAction: function (evnt) {
+    var keycode = 0, escapeKey = 0, key = 0;
+    if (evnt == null) { // ie
+      keycode = event.keyCode;
+      escapeKey = 27;
+    }
+    else { // mozilla
+      keycode = evnt.keyCode;
+      escapeKey = evnt.DOM_VK_ESCAPE;
+    }
+
+    key = String.fromCharCode(keycode).toLowerCase();
+    if ((key == 'x') || (key == 'o') || (key == 'c') || (keycode == escapeKey)) { // close lightbox
+      Lightbox._end();
+      return true;
+    } 
+    else if((key == 'p') || (keycode == 37)) { // display previous image
+      if (Lightbox._hasPrev()) {
+        Lightbox._disableKeyboardNav();
+        Lightbox._prevImage();
+        return true;
+      }
+    } 
+    else if((key == 'n') || (keycode == 39)) { // display next image
+      if (Lightbox._hasNext()) {
+        Lightbox._disableKeyboardNav();
+        Lightbox._nextImage();
+        return true;
+      }
+    }
+  return false;
+  },
+
+  _preloadNeighborImages: function () {
+    if (Lightbox._hasNext()) {
+      Lightbox._preloadNextImage = new Image();
+      Lightbox._preloadNextImage.src = Lightbox._imageArray[Lightbox._activeImage + 1][0];
+    }
+    if (Lightbox._hasPrev()) {
+      Lightbox._preloadPrevImage = new Image();
+      Lightbox._preloadPrevImage.src = Lightbox._imageArray[Lightbox._activeImage - 1][0];
+    }
+  },
+
+  _borderSize: 10,
+  _overlayDuration: 0.2,
+  _overlayBlockDuration: 0.6,
+  _resizeDuration: 0.4,
+  _minWidth: 0,
+  _imagePath: '/' + location.pathname.split('/',2)[1] + '/images/',
+  _opacity: 0.6,
+  _blockOpacity: 0.1,
+  _animate: true,
+  _text: "Image * of *",
+  _activeImage: 0,
+  _imageArray: []
+}
+
+// Returns array with x, y page scroll values.
+// Core code from - quirksmode.org
+function getPageScroll(){
+  var xScroll = 0, yScroll = 0;
+  if (self.pageYOffset) {
+    xScroll = self.pageXOffset;
+    yScroll = self.pageYOffset;
+  }
+  else if (document.documentElement && document.documentElement.scrollTop) {	// Explorer 6 Strict
+    xScroll = document.documentElement.scrollLeft;
+    yScroll = document.documentElement.scrollTop;
+  } 
+  else if (document.body) { // all other Explorers
+    xScroll = document.body.scrollLeft;	
+    yScroll = document.body.scrollTop;
+  }
+  return new Array(xScroll, yScroll)
+}
+
+// Returns array with page width, height and window width, height
+// Core code from - quirksmode.org
+// Edit for Firefox by pHaez
+function getPageSize() {
+  var xScroll = 0, yScroll = 0;
+  var docBody = document.body;
+  var docElem = document.documentElement;
+  if (window.innerHeight && window.scrollMaxY) {
+    xScroll = window.innerWidth + window.scrollMaxX;
+    yScroll = window.innerHeight + window.scrollMaxY;
+  }
+  else if (docBody.scrollHeight > docBody.offsetHeight) { // all but Explorer Mac
+    xScroll = docBody.scrollWidth;
+    yScroll = docBody.scrollHeight;
+  } 
+  else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
+    xScroll = docBody.offsetWidth;
+    yScroll = docBody.offsetHeight;
+  }
+
+  var windowWidth = 0, windowHeight = 0, pageHeight = 0, pageWidth = 0;
+  if (self.innerHeight) {	// all except Explorer
+    if(docElem.clientWidth) {
+      windowWidth = docElem.clientWidth; 
+    }
+    else {
+      windowWidth = self.innerWidth;
+    }
+    windowHeight = self.innerHeight;
+  }
+  else if (docElem && docElem.clientHeight) { // Explorer 6 Strict Mode
+    windowWidth = docElem.clientWidth;
+    windowHeight = docElem.clientHeight;
+  }
+  else { // other Explorers
+    windowWidth = docBody.clientWidth;
+    windowHeight = docBody.clientHeight;
+  }
+
+  // for small pages with total height less then height of the viewport
+  if (yScroll < windowHeight) {
+    pageHeight = windowHeight;
+  }	
+  else {
+    pageHeight = yScroll;
+  }
+
+  // for small pages with total width less then width of the viewport
+  if (xScroll < windowWidth) {
+    pageWidth = xScroll;
+  }
+  else {
+    pageWidth = windowWidth;
+  }
+  return new Array(pageWidth, pageHeight, windowWidth, windowHeight)
+}
+
+function showSelectBoxes() {
+  var selects = document.getElementsByTagName("select");
+  for (var i = 0, l = selects.length; i < l; i++) {
+    selects[i].style.visibility = "visible";
+  }
+}
+
+function hideSelectBoxes() {
+  var selects = document.getElementsByTagName("select");
+  for (var i = 0, l = selects.length; i < l; i++) {
+    selects[i].style.visibility = "hidden";
+  }
+}
+
+function showObjects() {
+  var objects = document.getElementsByTagName("object");
+  for (var i = 0, l = objects.length; i < l; i++) {
+    objects[i].style.visibility = "visible";
+  }
+
+  var embeds = document.getElementsByTagName("embed");
+  for (var i = 0, l = embeds.length; i < l; i++) {
+    embeds[i].style.visibility = "visible";
+  }
+}
+
+function hideObjects() {
+  var objects = document.getElementsByTagName("object");
+  for (var i = 0, l = objects.length; i < l; i++) {
+    objects[i].style.visibility = "hidden";
+  }
+
+  var embeds = document.getElementsByTagName("embed");
+  for (var i = 0, l = embeds.length; i < l; i++) {
+    embeds[i].style.visibility = "hidden";
+  }
+}
+
+// pause(numberMillis)
+// Pauses code execution for specified time. Uses busy code, not good.
+// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602
+// Help from Ran Bar-On [ran2103@gmail.com]
+function pause(ms) {
+  var date = new Date();
+  var curDate = null;
+  do {
+    curDate = new Date();
+  } while (curDate - date < ms);
+}
Index: branches/features/taskProcedureRework/web-app/js/overlayPane.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/overlayPane.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/overlayPane.js	(revision 753)
@@ -0,0 +1,77 @@
+
+function showElement(id) {
+    try {
+        if (typeof Effect != "undefined" && typeof Effect.Appear != "undefined") {
+                    if ($(id) && Element.visible(id) == false)
+            Effect.Appear(id,{duration:0.4,queue:'end'});
+        } else {
+            var el = document.getElementById(id)
+            if (el && el.style.display == 'none') {
+                el.style.display = 'block';
+            }
+        }
+    } catch (err) {alert(err)}
+    return false;
+}
+
+function hideElement(id) {
+    if (typeof Effect != "undefined" && typeof Effect.Fade != "undefined") {
+            if ($(id) && Element.visible(id))
+        Effect.Fade(id,{duration:0.4,queue:'end'});
+    } else {
+        var el = document.getElementById(id)
+        if (el && el.style.display != 'none') {
+            el.style.display = 'none';
+        }
+    }
+    return false;
+}
+
+function clearFilterPane(id) {
+    var form = document.getElementById(id)
+
+    for (var i = 0; i < form.elements.length; i++) {
+        var el = form.elements[i]
+        if (el.type == 'select-one') {
+            el.selectedIndex = 0
+        } else if (el.type == 'text' || el.type == 'textarea') { 
+            form.elements[i].value = ''
+        }
+    }
+}
+
+function filterOpChange(id, controlId) {
+    // id should be of the form op.propertyName
+    if (id.slice(0, 10) == 'filter.op.') {
+        var prop = id.substring(10)
+        var el = document.getElementById(id)
+        var selection = el.options[el.selectedIndex]
+        if (el) {
+            if (el.type == 'select-one') {
+                if (selection.value == 'Between') {
+                    showElement('between-span-'+prop)
+                } else {
+                    hideElement('between-span-'+prop)
+                }
+            }
+
+            var containerName = prop+'-container'
+            if (selection.value == 'IsNull' || selection.value == 'IsNotNull') {
+                hideElement(controlId);
+                // Take care of date picker fields we created.
+                if (document.getElementById(containerName)) hideElement(containerName)
+            } else {
+                showElement(controlId);
+                // Take care of date picker fields.
+                if (document.getElementById(containerName)) showElement(containerName)
+            }
+        }
+    }
+}
+
+function selectDefaultOperator(id) {
+    var dropdown = document.getElementById(id)
+    if (dropdown && dropdown.selectedIndex <= 0) {
+        dropdown.selectedIndex = 1
+    }
+}
Index: branches/features/taskProcedureRework/web-app/js/prototype/animation.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/animation.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/animation.js	(revision 753)
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 0.10.0
+*/
+YAHOO.util.Anim=function(el,attributes,duration,method){if(el){this.init(el,attributes,duration,method);}};YAHOO.util.Anim.prototype={doMethod:function(attribute,start,end){return this.method(this.currentFrame,start,end-start,this.totalFrames);},setAttribute:function(attribute,val,unit){YAHOO.util.Dom.setStyle(this.getEl(),attribute,val+unit);},getAttribute:function(attribute){return parseFloat(YAHOO.util.Dom.getStyle(this.getEl(),attribute));},defaultUnit:'px',defaultUnits:{opacity:' '},init:function(el,attributes,duration,method){var isAnimated=false;var startTime=null;var endTime=null;var actualFrames=0;var defaultValues={};el=YAHOO.util.Dom.get(el);this.attributes=attributes||{};this.duration=duration||1;this.method=method||YAHOO.util.Easing.easeNone;this.useSeconds=true;this.currentFrame=0;this.totalFrames=YAHOO.util.AnimMgr.fps;this.getEl=function(){return el;};this.setDefault=function(attribute,val){if(val.constructor!=Array&&(val=='auto'||isNaN(val))){switch(attribute){case'width':val=el.clientWidth||el.offsetWidth;break;case'height':val=el.clientHeight||el.offsetHeight;break;case'left':if(YAHOO.util.Dom.getStyle(el,'position')=='absolute'){val=el.offsetLeft;}else{val=0;}break;case'top':if(YAHOO.util.Dom.getStyle(el,'position')=='absolute'){val=el.offsetTop;}else{val=0;}break;default:val=0;}}defaultValues[attribute]=val;};this.getDefault=function(attribute){return defaultValues[attribute];};this.isAnimated=function(){return isAnimated;};this.getStartTime=function(){return startTime;};this.animate=function(){if(this.isAnimated()){return false;}this.onStart.fire();this._onStart.fire();this.totalFrames=(this.useSeconds)?Math.ceil(YAHOO.util.AnimMgr.fps*this.duration):this.duration;YAHOO.util.AnimMgr.registerElement(this);var attributes=this.attributes;var el=this.getEl();var val;for(var attribute in attributes){val=this.getAttribute(attribute);this.setDefault(attribute,val);}isAnimated=true;actualFrames=0;startTime=new Date();};this.stop=function(){if(!this.isAnimated()){return false;}this.currentFrame=0;endTime=new Date();var data={time:endTime,duration:endTime-startTime,frames:actualFrames,fps:actualFrames/this.duration};isAnimated=false;actualFrames=0;this.onComplete.fire(data);};var onTween=function(){var start;var end=null;var val;var unit;var attributes=this['attributes'];for(var attribute in attributes){unit=attributes[attribute]['unit']||this.defaultUnits[attribute]||this.defaultUnit;if(typeof attributes[attribute]['from']!='undefined'){start=attributes[attribute]['from'];}else{start=this.getDefault(attribute);}if(typeof attributes[attribute]['to']!='undefined'){end=attributes[attribute]['to'];}else if(typeof attributes[attribute]['by']!='undefined'){if(start.constructor==Array){end=[];for(var i=0,len=start.length;i<len;++i){end[i]=start[i]+attributes[attribute]['by'][i];}}else{end=start+attributes[attribute]['by'];}}if(end!==null&&typeof end!='undefined'){val=this.doMethod(attribute,start,end);if((attribute=='width'||attribute=='height'||attribute=='opacity')&&val<0){val=0;}this.setAttribute(attribute,val,unit);}}actualFrames+=1;};this._onStart=new YAHOO.util.CustomEvent('_onStart',this);this.onStart=new YAHOO.util.CustomEvent('start',this);this.onTween=new YAHOO.util.CustomEvent('tween',this);this._onTween=new YAHOO.util.CustomEvent('_tween',this);this.onComplete=new YAHOO.util.CustomEvent('complete',this);this._onTween.subscribe(onTween);}};YAHOO.util.AnimMgr=new function(){var thread=null;var queue=[];var tweenCount=0;this.fps=200;this.delay=1;this.registerElement=function(tween){if(tween.isAnimated()){return false;}queue[queue.length]=tween;tweenCount+=1;this.start();};this.start=function(){if(thread===null){thread=setInterval(this.run,this.delay);}};this.stop=function(tween){if(!tween){clearInterval(thread);for(var i=0,len=queue.length;i<len;++i){if(queue[i].isAnimated()){queue[i].stop();}}queue=[];thread=null;tweenCount=0;}else{tween.stop();tweenCount-=1;if(tweenCount<=0){this.stop();}}};this.run=function(){for(var i=0,len=queue.length;i<len;++i){var tween=queue[i];if(!tween||!tween.isAnimated()){continue;}if(tween.currentFrame<tween.totalFrames||tween.totalFrames===null){tween.currentFrame+=1;if(tween.useSeconds){correctFrame(tween);}tween.onTween.fire();tween._onTween.fire();}else{YAHOO.util.AnimMgr.stop(tween);}}};var correctFrame=function(tween){var frames=tween.totalFrames;var frame=tween.currentFrame;var expected=(tween.currentFrame*tween.duration*1000/tween.totalFrames);var elapsed=(new Date()-tween.getStartTime());var tweak=0;if(elapsed<tween.duration*1000){tweak=Math.round((elapsed/expected-1)*tween.currentFrame);}else{tweak=frames-(frame+1);}if(tweak>0&&isFinite(tweak)){if(tween.currentFrame+tweak>=frames){tweak=frames-(frame+1);}tween.currentFrame+=tweak;}};};YAHOO.util.Bezier=new function(){this.getPosition=function(points,t){var n=points.length;var tmp=[];for(var i=0;i<n;++i){tmp[i]=[points[i][0],points[i][1]];}for(var j=1;j<n;++j){for(i=0;i<n-j;++i){tmp[i][0]=(1-t)*tmp[i][0]+t*tmp[parseInt(i+1,10)][0];tmp[i][1]=(1-t)*tmp[i][1]+t*tmp[parseInt(i+1,10)][1];}}return[tmp[0][0],tmp[0][1]];};};YAHOO.util.Easing=new function(){this.easeNone=function(t,b,c,d){return b+c*(t/=d);};this.easeIn=function(t,b,c,d){return b+c*((t/=d)*t*t);};this.easeOut=function(t,b,c,d){var ts=(t/=d)*t;var tc=ts*t;return b+c*(tc+-3*ts+3*t);};this.easeBoth=function(t,b,c,d){var ts=(t/=d)*t;var tc=ts*t;return b+c*(-2*tc+3*ts);};this.backIn=function(t,b,c,d){var ts=(t/=d)*t;var tc=ts*t;return b+c*(-3.4005*tc*ts+10.2*ts*ts+-6.2*tc+0.4*ts);};this.backOut=function(t,b,c,d){var ts=(t/=d)*t;var tc=ts*t;return b+c*(8.292*tc*ts+-21.88*ts*ts+22.08*tc+-12.69*ts+5.1975*t);};this.backBoth=function(t,b,c,d){var ts=(t/=d)*t;var tc=ts*t;return b+c*(0.402*tc*ts+-2.1525*ts*ts+-3.2*tc+8*ts+-2.05*t);};};YAHOO.util.Motion=function(el,attributes,duration,method){if(el){this.initMotion(el,attributes,duration,method);}};YAHOO.util.Motion.prototype=new YAHOO.util.Anim();YAHOO.util.Motion.prototype.defaultUnits.points='px';YAHOO.util.Motion.prototype.doMethod=function(attribute,start,end){var val=null;if(attribute=='points'){var translatedPoints=this.getTranslatedPoints();var t=this.method(this.currentFrame,0,100,this.totalFrames)/100;if(translatedPoints){val=YAHOO.util.Bezier.getPosition(translatedPoints,t);}}else{val=this.method(this.currentFrame,start,end-start,this.totalFrames);}return val;};YAHOO.util.Motion.prototype.getAttribute=function(attribute){var val=null;if(attribute=='points'){val=[this.getAttribute('left'),this.getAttribute('top')];if(isNaN(val[0])){val[0]=0;}if(isNaN(val[1])){val[1]=0;}}else{val=parseFloat(YAHOO.util.Dom.getStyle(this.getEl(),attribute));}return val;};YAHOO.util.Motion.prototype.setAttribute=function(attribute,val,unit){if(attribute=='points'){YAHOO.util.Dom.setStyle(this.getEl(),'left',val[0]+unit);YAHOO.util.Dom.setStyle(this.getEl(),'top',val[1]+unit);}else{YAHOO.util.Dom.setStyle(this.getEl(),attribute,val+unit);}};YAHOO.util.Motion.prototype.initMotion=function(el,attributes,duration,method){YAHOO.util.Anim.call(this,el,attributes,duration,method);attributes=attributes||{};attributes.points=attributes.points||{};attributes.points.control=attributes.points.control||[];this.attributes=attributes;var start;var end=null;var translatedPoints=null;this.getTranslatedPoints=function(){return translatedPoints;};var translateValues=function(val,self){var pageXY=YAHOO.util.Dom.getXY(self.getEl());val=[val[0]-pageXY[0]+start[0],val[1]-pageXY[1]+start[1]];return val;};var onStart=function(){start=this.getAttribute('points');var attributes=this.attributes;var control=attributes['points']['control']||[];if(control.length>0&&control[0].constructor!=Array){control=[control];}if(YAHOO.util.Dom.getStyle(this.getEl(),'position')=='static'){YAHOO.util.Dom.setStyle(this.getEl(),'position','relative');}if(typeof attributes['points']['from']!='undefined'){YAHOO.util.Dom.setXY(this.getEl(),attributes['points']['from']);start=this.getAttribute('points');}else if((start[0]===0||start[1]===0)){YAHOO.util.Dom.setXY(this.getEl(),YAHOO.util.Dom.getXY(this.getEl()));start=this.getAttribute('points');}var i,len;if(typeof attributes['points']['to']!='undefined'){end=translateValues(attributes['points']['to'],this);for(i=0,len=control.length;i<len;++i){control[i]=translateValues(control[i],this);}}else if(typeof attributes['points']['by']!='undefined'){end=[start[0]+attributes['points']['by'][0],start[1]+attributes['points']['by'][1]];for(i=0,len=control.length;i<len;++i){control[i]=[start[0]+control[i][0],start[1]+control[i][1]];}}if(end){translatedPoints=[start];if(control.length>0){translatedPoints=translatedPoints.concat(control);}translatedPoints[translatedPoints.length]=end;}};this._onStart.subscribe(onStart);};YAHOO.util.Scroll=function(el,attributes,duration,method){if(el){YAHOO.util.Anim.call(this,el,attributes,duration,method);}};YAHOO.util.Scroll.prototype=new YAHOO.util.Anim();YAHOO.util.Scroll.prototype.defaultUnits.scroll=' ';YAHOO.util.Scroll.prototype.doMethod=function(attribute,start,end){var val=null;if(attribute=='scroll'){val=[this.method(this.currentFrame,start[0],end[0]-start[0],this.totalFrames),this.method(this.currentFrame,start[1],end[1]-start[1],this.totalFrames)];}else{val=this.method(this.currentFrame,start,end-start,this.totalFrames);}return val;};YAHOO.util.Scroll.prototype.getAttribute=function(attribute){var val=null;var el=this.getEl();if(attribute=='scroll'){val=[el.scrollLeft,el.scrollTop];}else{val=parseFloat(YAHOO.util.Dom.getStyle(el,attribute));}return val;};YAHOO.util.Scroll.prototype.setAttribute=function(attribute,val,unit){var el=this.getEl();if(attribute=='scroll'){el.scrollLeft=val[0];el.scrollTop=val[1];}else{YAHOO.util.Dom.setStyle(el,attribute,val+unit);}};
Index: branches/features/taskProcedureRework/web-app/js/prototype/builder.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/builder.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/builder.js	(revision 753)
@@ -0,0 +1,136 @@
+// script.aculo.us builder.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Builder = {
+  NODEMAP: {
+    AREA: 'map',
+    CAPTION: 'table',
+    COL: 'table',
+    COLGROUP: 'table',
+    LEGEND: 'fieldset',
+    OPTGROUP: 'select',
+    OPTION: 'select',
+    PARAM: 'object',
+    TBODY: 'table',
+    TD: 'table',
+    TFOOT: 'table',
+    TH: 'table',
+    THEAD: 'table',
+    TR: 'table'
+  },
+  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+  //       due to a Firefox bug
+  node: function(elementName) {
+    elementName = elementName.toUpperCase();
+    
+    // try innerHTML approach
+    var parentTag = this.NODEMAP[elementName] || 'div';
+    var parentElement = document.createElement(parentTag);
+    try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+      parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+    } catch(e) {}
+    var element = parentElement.firstChild || null;
+      
+    // see if browser added wrapping tags
+    if(element && (element.tagName.toUpperCase() != elementName))
+      element = element.getElementsByTagName(elementName)[0];
+    
+    // fallback to createElement approach
+    if(!element) element = document.createElement(elementName);
+    
+    // abort if nothing could be created
+    if(!element) return;
+
+    // attributes (or text)
+    if(arguments[1])
+      if(this._isStringOrNumber(arguments[1]) ||
+        (arguments[1] instanceof Array) ||
+        arguments[1].tagName) {
+          this._children(element, arguments[1]);
+        } else {
+          var attrs = this._attributes(arguments[1]);
+          if(attrs.length) {
+            try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
+              parentElement.innerHTML = "<" +elementName + " " +
+                attrs + "></" + elementName + ">";
+            } catch(e) {}
+            element = parentElement.firstChild || null;
+            // workaround firefox 1.0.X bug
+            if(!element) {
+              element = document.createElement(elementName);
+              for(attr in arguments[1]) 
+                element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+            }
+            if(element.tagName.toUpperCase() != elementName)
+              element = parentElement.getElementsByTagName(elementName)[0];
+          }
+        } 
+
+    // text, or array of children
+    if(arguments[2])
+      this._children(element, arguments[2]);
+
+     return element;
+  },
+  _text: function(text) {
+     return document.createTextNode(text);
+  },
+
+  ATTR_MAP: {
+    'className': 'class',
+    'htmlFor': 'for'
+  },
+
+  _attributes: function(attributes) {
+    var attrs = [];
+    for(attribute in attributes)
+      attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
+          '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
+    return attrs.join(" ");
+  },
+  _children: function(element, children) {
+    if(children.tagName) {
+      element.appendChild(children);
+      return;
+    }
+    if(typeof children=='object') { // array can hold nodes and text
+      children.flatten().each( function(e) {
+        if(typeof e=='object')
+          element.appendChild(e)
+        else
+          if(Builder._isStringOrNumber(e))
+            element.appendChild(Builder._text(e));
+      });
+    } else
+      if(Builder._isStringOrNumber(children))
+        element.appendChild(Builder._text(children));
+  },
+  _isStringOrNumber: function(param) {
+    return(typeof param=='string' || typeof param=='number');
+  },
+  build: function(html) {
+    var element = this.node('div');
+    $(element).update(html.strip());
+    return element.down();
+  },
+  dump: function(scope) { 
+    if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope 
+  
+    var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
+      "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
+      "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
+      "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
+      "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
+      "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
+  
+    tags.each( function(tag){ 
+      scope[tag] = function() { 
+        return Builder.node.apply(Builder, [tag].concat($A(arguments)));  
+      } 
+    });
+  }
+}
Index: branches/features/taskProcedureRework/web-app/js/prototype/controls.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/controls.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/controls.js	(revision 753)
@@ -0,0 +1,965 @@
+// script.aculo.us controls.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+//           (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+// Contributors:
+//  Richard Livsey
+//  Rahul Bhargava
+//  Rob Wills
+// 
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// Autocompleter.Base handles all the autocompletion functionality 
+// that's independent of the data source for autocompletion. This
+// includes drawing the autocompletion menu, observing keyboard
+// and mouse events, and similar.
+//
+// Specific autocompleters need to provide, at the very least, 
+// a getUpdatedChoices function that will be invoked every time
+// the text inside the monitored textbox changes. This method 
+// should get the text for which to provide autocompletion by
+// invoking this.getToken(), NOT by directly accessing
+// this.element.value. This is to allow incremental tokenized
+// autocompletion. Specific auto-completion logic (AJAX, etc)
+// belongs in getUpdatedChoices.
+//
+// Tokenized incremental autocompletion is enabled automatically
+// when an autocompleter is instantiated with the 'tokens' option
+// in the options parameter, e.g.:
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+// will incrementally autocomplete with a comma as the token.
+// Additionally, ',' in the above example can be replaced with
+// a token array, e.g. { tokens: [',', '\n'] } which
+// enables autocompletion on multiple tokens. This is most 
+// useful when one of the tokens is \n (a newline), as it 
+// allows smart autocompletion after linebreaks.
+
+if(typeof Effect == 'undefined')
+  throw("controls.js requires including script.aculo.us' effects.js library");
+
+var Autocompleter = { }
+Autocompleter.Base = Class.create({
+  baseInitialize: function(element, update, options) {
+    element          = $(element)
+    this.element     = element; 
+    this.update      = $(update);  
+    this.hasFocus    = false; 
+    this.changed     = false; 
+    this.active      = false; 
+    this.index       = 0;     
+    this.entryCount  = 0;
+    this.oldElementValue = this.element.value;
+
+    if(this.setOptions)
+      this.setOptions(options);
+    else
+      this.options = options || { };
+
+    this.options.paramName    = this.options.paramName || this.element.name;
+    this.options.tokens       = this.options.tokens || [];
+    this.options.frequency    = this.options.frequency || 0.4;
+    this.options.minChars     = this.options.minChars || 1;
+    this.options.onShow       = this.options.onShow || 
+      function(element, update){ 
+        if(!update.style.position || update.style.position=='absolute') {
+          update.style.position = 'absolute';
+          Position.clone(element, update, {
+            setHeight: false, 
+            offsetTop: element.offsetHeight
+          });
+        }
+        Effect.Appear(update,{duration:0.15});
+      };
+    this.options.onHide = this.options.onHide || 
+      function(element, update){ new Effect.Fade(update,{duration:0.15}) };
+
+    if(typeof(this.options.tokens) == 'string') 
+      this.options.tokens = new Array(this.options.tokens);
+    // Force carriage returns as token delimiters anyway
+    if (!this.options.tokens.include('\n'))
+      this.options.tokens.push('\n');
+
+    this.observer = null;
+    
+    this.element.setAttribute('autocomplete','off');
+
+    Element.hide(this.update);
+
+    Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
+    Event.observe(this.element, 'keypress', this.onKeyPress.bindAsEventListener(this));
+  },
+
+  show: function() {
+    if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
+    if(!this.iefix && 
+      (Prototype.Browser.IE) &&
+      (Element.getStyle(this.update, 'position')=='absolute')) {
+      new Insertion.After(this.update, 
+       '<iframe id="' + this.update.id + '_iefix" '+
+       'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+       'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+      this.iefix = $(this.update.id+'_iefix');
+    }
+    if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+  },
+  
+  fixIEOverlapping: function() {
+    Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
+    this.iefix.style.zIndex = 1;
+    this.update.style.zIndex = 2;
+    Element.show(this.iefix);
+  },
+
+  hide: function() {
+    this.stopIndicator();
+    if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
+    if(this.iefix) Element.hide(this.iefix);
+  },
+
+  startIndicator: function() {
+    if(this.options.indicator) Element.show(this.options.indicator);
+  },
+
+  stopIndicator: function() {
+    if(this.options.indicator) Element.hide(this.options.indicator);
+  },
+
+  onKeyPress: function(event) {
+    if(this.active)
+      switch(event.keyCode) {
+       case Event.KEY_TAB:
+       case Event.KEY_RETURN:
+         this.selectEntry();
+         Event.stop(event);
+       case Event.KEY_ESC:
+         this.hide();
+         this.active = false;
+         Event.stop(event);
+         return;
+       case Event.KEY_LEFT:
+       case Event.KEY_RIGHT:
+         return;
+       case Event.KEY_UP:
+         this.markPrevious();
+         this.render();
+         if(Prototype.Browser.WebKit) Event.stop(event);
+         return;
+       case Event.KEY_DOWN:
+         this.markNext();
+         this.render();
+         if(Prototype.Browser.WebKit) Event.stop(event);
+         return;
+      }
+     else 
+       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || 
+         (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
+
+    this.changed = true;
+    this.hasFocus = true;
+
+    if(this.observer) clearTimeout(this.observer);
+      this.observer = 
+        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
+  },
+
+  activate: function() {
+    this.changed = false;
+    this.hasFocus = true;
+    this.getUpdatedChoices();
+  },
+
+  onHover: function(event) {
+    var element = Event.findElement(event, 'LI');
+    if(this.index != element.autocompleteIndex) 
+    {
+        this.index = element.autocompleteIndex;
+        this.render();
+    }
+    Event.stop(event);
+  },
+  
+  onClick: function(event) {
+    var element = Event.findElement(event, 'LI');
+    this.index = element.autocompleteIndex;
+    this.selectEntry();
+    this.hide();
+  },
+  
+  onBlur: function(event) {
+    // needed to make click events working
+    setTimeout(this.hide.bind(this), 250);
+    this.hasFocus = false;
+    this.active = false;     
+  }, 
+  
+  render: function() {
+    if(this.entryCount > 0) {
+      for (var i = 0; i < this.entryCount; i++)
+        this.index==i ? 
+          Element.addClassName(this.getEntry(i),"selected") : 
+          Element.removeClassName(this.getEntry(i),"selected");
+      if(this.hasFocus) { 
+        this.show();
+        this.active = true;
+      }
+    } else {
+      this.active = false;
+      this.hide();
+    }
+  },
+  
+  markPrevious: function() {
+    if(this.index > 0) this.index--
+      else this.index = this.entryCount-1;
+    this.getEntry(this.index).scrollIntoView(true);
+  },
+  
+  markNext: function() {
+    if(this.index < this.entryCount-1) this.index++
+      else this.index = 0;
+    this.getEntry(this.index).scrollIntoView(false);
+  },
+  
+  getEntry: function(index) {
+    return this.update.firstChild.childNodes[index];
+  },
+  
+  getCurrentEntry: function() {
+    return this.getEntry(this.index);
+  },
+  
+  selectEntry: function() {
+    this.active = false;
+    this.updateElement(this.getCurrentEntry());
+  },
+
+  updateElement: function(selectedElement) {
+    if (this.options.updateElement) {
+      this.options.updateElement(selectedElement);
+      return;
+    }
+    var value = '';
+    if (this.options.select) {
+      var nodes = $(selectedElement).select('.' + this.options.select) || [];
+      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
+    } else
+      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
+    
+    var bounds = this.getTokenBounds();
+    if (bounds[0] != -1) {
+      var newValue = this.element.value.substr(0, bounds[0]);
+      var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
+      if (whitespace)
+        newValue += whitespace[0];
+      this.element.value = newValue + value + this.element.value.substr(bounds[1]);
+    } else {
+      this.element.value = value;
+    }
+    this.oldElementValue = this.element.value;
+    this.element.focus();
+    
+    if (this.options.afterUpdateElement)
+      this.options.afterUpdateElement(this.element, selectedElement);
+  },
+
+  updateChoices: function(choices) {
+    if(!this.changed && this.hasFocus) {
+      this.update.innerHTML = choices;
+      Element.cleanWhitespace(this.update);
+      Element.cleanWhitespace(this.update.down());
+
+      if(this.update.firstChild && this.update.down().childNodes) {
+        this.entryCount = 
+          this.update.down().childNodes.length;
+        for (var i = 0; i < this.entryCount; i++) {
+          var entry = this.getEntry(i);
+          entry.autocompleteIndex = i;
+          this.addObservers(entry);
+        }
+      } else { 
+        this.entryCount = 0;
+      }
+
+      this.stopIndicator();
+      this.index = 0;
+      
+      if(this.entryCount==1 && this.options.autoSelect) {
+        this.selectEntry();
+        this.hide();
+      } else {
+        this.render();
+      }
+    }
+  },
+
+  addObservers: function(element) {
+    Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
+    Event.observe(element, "click", this.onClick.bindAsEventListener(this));
+  },
+
+  onObserverEvent: function() {
+    this.changed = false;   
+    this.tokenBounds = null;
+    if(this.getToken().length>=this.options.minChars) {
+      this.getUpdatedChoices();
+    } else {
+      this.active = false;
+      this.hide();
+    }
+    this.oldElementValue = this.element.value;
+  },
+
+  getToken: function() {
+    var bounds = this.getTokenBounds();
+    return this.element.value.substring(bounds[0], bounds[1]).strip();
+  },
+
+  getTokenBounds: function() {
+    if (null != this.tokenBounds) return this.tokenBounds;
+    var value = this.element.value;
+    if (value.strip().empty()) return [-1, 0];
+    var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
+    var offset = (diff == this.oldElementValue.length ? 1 : 0);
+    var prevTokenPos = -1, nextTokenPos = value.length;
+    var tp;
+    for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
+      tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
+      if (tp > prevTokenPos) prevTokenPos = tp;
+      tp = value.indexOf(this.options.tokens[index], diff + offset);
+      if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
+    }
+    return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
+  }
+});
+
+Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
+  var boundary = Math.min(newS.length, oldS.length);
+  for (var index = 0; index < boundary; ++index)
+    if (newS[index] != oldS[index])
+      return index;
+  return boundary;
+};
+
+Ajax.Autocompleter = Class.create(Autocompleter.Base, {
+  initialize: function(element, update, url, options) {
+    this.baseInitialize(element, update, options);
+    this.options.asynchronous  = true;
+    this.options.onComplete    = this.onComplete.bind(this);
+    this.options.defaultParams = this.options.parameters || null;
+    this.url                   = url;
+  },
+
+  getUpdatedChoices: function() {
+    this.startIndicator();
+    
+    var entry = encodeURIComponent(this.options.paramName) + '=' + 
+      encodeURIComponent(this.getToken());
+
+    this.options.parameters = this.options.callback ?
+      this.options.callback(this.element, entry) : entry;
+
+    if(this.options.defaultParams) 
+      this.options.parameters += '&' + this.options.defaultParams;
+    
+    new Ajax.Request(this.url, this.options);
+  },
+
+  onComplete: function(request) {
+    this.updateChoices(request.responseText);
+  }
+});
+
+// The local array autocompleter. Used when you'd prefer to
+// inject an array of autocompletion options into the page, rather
+// than sending out Ajax queries, which can be quite slow sometimes.
+//
+// The constructor takes four parameters. The first two are, as usual,
+// the id of the monitored textbox, and id of the autocompletion menu.
+// The third is the array you want to autocomplete from, and the fourth
+// is the options block.
+//
+// Extra local autocompletion options:
+// - choices - How many autocompletion choices to offer
+//
+// - partialSearch - If false, the autocompleter will match entered
+//                    text only at the beginning of strings in the 
+//                    autocomplete array. Defaults to true, which will
+//                    match text at the beginning of any *word* in the
+//                    strings in the autocomplete array. If you want to
+//                    search anywhere in the string, additionally set
+//                    the option fullSearch to true (default: off).
+//
+// - fullSsearch - Search anywhere in autocomplete array strings.
+//
+// - partialChars - How many characters to enter before triggering
+//                   a partial match (unlike minChars, which defines
+//                   how many characters are required to do any match
+//                   at all). Defaults to 2.
+//
+// - ignoreCase - Whether to ignore case when autocompleting.
+//                 Defaults to true.
+//
+// It's possible to pass in a custom function as the 'selector' 
+// option, if you prefer to write your own autocompletion logic.
+// In that case, the other options above will not apply unless
+// you support them.
+
+Autocompleter.Local = Class.create(Autocompleter.Base, {
+  initialize: function(element, update, array, options) {
+    this.baseInitialize(element, update, options);
+    this.options.array = array;
+  },
+
+  getUpdatedChoices: function() {
+    this.updateChoices(this.options.selector(this));
+  },
+
+  setOptions: function(options) {
+    this.options = Object.extend({
+      choices: 10,
+      partialSearch: true,
+      partialChars: 2,
+      ignoreCase: true,
+      fullSearch: false,
+      selector: function(instance) {
+        var ret       = []; // Beginning matches
+        var partial   = []; // Inside matches
+        var entry     = instance.getToken();
+        var count     = 0;
+
+        for (var i = 0; i < instance.options.array.length &&  
+          ret.length < instance.options.choices ; i++) { 
+
+          var elem = instance.options.array[i];
+          var foundPos = instance.options.ignoreCase ? 
+            elem.toLowerCase().indexOf(entry.toLowerCase()) : 
+            elem.indexOf(entry);
+
+          while (foundPos != -1) {
+            if (foundPos == 0 && elem.length != entry.length) { 
+              ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + 
+                elem.substr(entry.length) + "</li>");
+              break;
+            } else if (entry.length >= instance.options.partialChars && 
+              instance.options.partialSearch && foundPos != -1) {
+              if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
+                partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
+                  elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
+                  foundPos + entry.length) + "</li>");
+                break;
+              }
+            }
+
+            foundPos = instance.options.ignoreCase ? 
+              elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : 
+              elem.indexOf(entry, foundPos + 1);
+
+          }
+        }
+        if (partial.length)
+          ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+        return "<ul>" + ret.join('') + "</ul>";
+      }
+    }, options || { });
+  }
+});
+
+// AJAX in-place editor and collection editor
+// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
+
+// Use this if you notice weird scrolling problems on some browsers,
+// the DOM might be a bit confused when this gets called so do this
+// waits 1 ms (with setTimeout) until it does the activation
+Field.scrollFreeActivate = function(field) {
+  setTimeout(function() {
+    Field.activate(field);
+  }, 1);
+}
+
+Ajax.InPlaceEditor = Class.create({
+  initialize: function(element, url, options) {
+    this.url = url;
+    this.element = element = $(element);
+    this.prepareOptions();
+    this._controls = { };
+    arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
+    Object.extend(this.options, options || { });
+    if (!this.options.formId && this.element.id) {
+      this.options.formId = this.element.id + '-inplaceeditor';
+      if ($(this.options.formId))
+        this.options.formId = '';
+    }
+    if (this.options.externalControl)
+      this.options.externalControl = $(this.options.externalControl);
+    if (!this.options.externalControl)
+      this.options.externalControlOnly = false;
+    this._originalBackground = this.element.getStyle('background-color') || 'transparent';
+    this.element.title = this.options.clickToEditText;
+    this._boundCancelHandler = this.handleFormCancellation.bind(this);
+    this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
+    this._boundFailureHandler = this.handleAJAXFailure.bind(this);
+    this._boundSubmitHandler = this.handleFormSubmission.bind(this);
+    this._boundWrapperHandler = this.wrapUp.bind(this);
+    this.registerListeners();
+  },
+  checkForEscapeOrReturn: function(e) {
+    if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
+    if (Event.KEY_ESC == e.keyCode)
+      this.handleFormCancellation(e);
+    else if (Event.KEY_RETURN == e.keyCode)
+      this.handleFormSubmission(e);
+  },
+  createControl: function(mode, handler, extraClasses) {
+    var control = this.options[mode + 'Control'];
+    var text = this.options[mode + 'Text'];
+    if ('button' == control) {
+      var btn = document.createElement('input');
+      btn.type = 'submit';
+      btn.value = text;
+      btn.className = 'editor_' + mode + '_button';
+      if ('cancel' == mode)
+        btn.onclick = this._boundCancelHandler;
+      this._form.appendChild(btn);
+      this._controls[mode] = btn;
+    } else if ('link' == control) {
+      var link = document.createElement('a');
+      link.href = '#';
+      link.appendChild(document.createTextNode(text));
+      link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
+      link.className = 'editor_' + mode + '_link';
+      if (extraClasses)
+        link.className += ' ' + extraClasses;
+      this._form.appendChild(link);
+      this._controls[mode] = link;
+    }
+  },
+  createEditField: function() {
+    var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
+    var fld;
+    if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
+      fld = document.createElement('input');
+      fld.type = 'text';
+      var size = this.options.size || this.options.cols || 0;
+      if (0 < size) fld.size = size;
+    } else {
+      fld = document.createElement('textarea');
+      fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
+      fld.cols = this.options.cols || 40;
+    }
+    fld.name = this.options.paramName;
+    fld.value = text; // No HTML breaks conversion anymore
+    fld.className = 'editor_field';
+    if (this.options.submitOnBlur)
+      fld.onblur = this._boundSubmitHandler;
+    this._controls.editor = fld;
+    if (this.options.loadTextURL)
+      this.loadExternalText();
+    this._form.appendChild(this._controls.editor);
+  },
+  createForm: function() {
+    var ipe = this;
+    function addText(mode, condition) {
+      var text = ipe.options['text' + mode + 'Controls'];
+      if (!text || condition === false) return;
+      ipe._form.appendChild(document.createTextNode(text));
+    };
+    this._form = $(document.createElement('form'));
+    this._form.id = this.options.formId;
+    this._form.addClassName(this.options.formClassName);
+    this._form.onsubmit = this._boundSubmitHandler;
+    this.createEditField();
+    if ('textarea' == this._controls.editor.tagName.toLowerCase())
+      this._form.appendChild(document.createElement('br'));
+    if (this.options.onFormCustomization)
+      this.options.onFormCustomization(this, this._form);
+    addText('Before', this.options.okControl || this.options.cancelControl);
+    this.createControl('ok', this._boundSubmitHandler);
+    addText('Between', this.options.okControl && this.options.cancelControl);
+    this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
+    addText('After', this.options.okControl || this.options.cancelControl);
+  },
+  destroy: function() {
+    if (this._oldInnerHTML)
+      this.element.innerHTML = this._oldInnerHTML;
+    this.leaveEditMode();
+    this.unregisterListeners();
+  },
+  enterEditMode: function(e) {
+    if (this._saving || this._editing) return;
+    this._editing = true;
+    this.triggerCallback('onEnterEditMode');
+    if (this.options.externalControl)
+      this.options.externalControl.hide();
+    this.element.hide();
+    this.createForm();
+    this.element.parentNode.insertBefore(this._form, this.element);
+    if (!this.options.loadTextURL)
+      this.postProcessEditField();
+    if (e) Event.stop(e);
+  },
+  enterHover: function(e) {
+    if (this.options.hoverClassName)
+      this.element.addClassName(this.options.hoverClassName);
+    if (this._saving) return;
+    this.triggerCallback('onEnterHover');
+  },
+  getText: function() {
+    return this.element.innerHTML;
+  },
+  handleAJAXFailure: function(transport) {
+    this.triggerCallback('onFailure', transport);
+    if (this._oldInnerHTML) {
+      this.element.innerHTML = this._oldInnerHTML;
+      this._oldInnerHTML = null;
+    }
+  },
+  handleFormCancellation: function(e) {
+    this.wrapUp();
+    if (e) Event.stop(e);
+  },
+  handleFormSubmission: function(e) {
+    var form = this._form;
+    var value = $F(this._controls.editor);
+    this.prepareSubmission();
+    var params = this.options.callback(form, value) || '';
+    if (Object.isString(params))
+      params = params.toQueryParams();
+    params.editorId = this.element.id;
+    if (this.options.htmlResponse) {
+      var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
+      Object.extend(options, {
+        parameters: params,
+        onComplete: this._boundWrapperHandler,
+        onFailure: this._boundFailureHandler
+      });
+      new Ajax.Updater({ success: this.element }, this.url, options);
+    } else {
+      var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+      Object.extend(options, {
+        parameters: params,
+        onComplete: this._boundWrapperHandler,
+        onFailure: this._boundFailureHandler
+      });
+      new Ajax.Request(this.url, options);
+    }
+    if (e) Event.stop(e);
+  },
+  leaveEditMode: function() {
+    this.element.removeClassName(this.options.savingClassName);
+    this.removeForm();
+    this.leaveHover();
+    this.element.style.backgroundColor = this._originalBackground;
+    this.element.show();
+    if (this.options.externalControl)
+      this.options.externalControl.show();
+    this._saving = false;
+    this._editing = false;
+    this._oldInnerHTML = null;
+    this.triggerCallback('onLeaveEditMode');
+  },
+  leaveHover: function(e) {
+    if (this.options.hoverClassName)
+      this.element.removeClassName(this.options.hoverClassName);
+    if (this._saving) return;
+    this.triggerCallback('onLeaveHover');
+  },
+  loadExternalText: function() {
+    this._form.addClassName(this.options.loadingClassName);
+    this._controls.editor.disabled = true;
+    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+    Object.extend(options, {
+      parameters: 'editorId=' + encodeURIComponent(this.element.id),
+      onComplete: Prototype.emptyFunction,
+      onSuccess: function(transport) {
+        this._form.removeClassName(this.options.loadingClassName);
+        var text = transport.responseText;
+        if (this.options.stripLoadedTextTags)
+          text = text.stripTags();
+        this._controls.editor.value = text;
+        this._controls.editor.disabled = false;
+        this.postProcessEditField();
+      }.bind(this),
+      onFailure: this._boundFailureHandler
+    });
+    new Ajax.Request(this.options.loadTextURL, options);
+  },
+  postProcessEditField: function() {
+    var fpc = this.options.fieldPostCreation;
+    if (fpc)
+      $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
+  },
+  prepareOptions: function() {
+    this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
+    Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
+    [this._extraDefaultOptions].flatten().compact().each(function(defs) {
+      Object.extend(this.options, defs);
+    }.bind(this));
+  },
+  prepareSubmission: function() {
+    this._saving = true;
+    this.removeForm();
+    this.leaveHover();
+    this.showSaving();
+  },
+  registerListeners: function() {
+    this._listeners = { };
+    var listener;
+    $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
+      listener = this[pair.value].bind(this);
+      this._listeners[pair.key] = listener;
+      if (!this.options.externalControlOnly)
+        this.element.observe(pair.key, listener);
+      if (this.options.externalControl)
+        this.options.externalControl.observe(pair.key, listener);
+    }.bind(this));
+  },
+  removeForm: function() {
+    if (!this._form) return;
+    this._form.remove();
+    this._form = null;
+    this._controls = { };
+  },
+  showSaving: function() {
+    this._oldInnerHTML = this.element.innerHTML;
+    this.element.innerHTML = this.options.savingText;
+    this.element.addClassName(this.options.savingClassName);
+    this.element.style.backgroundColor = this._originalBackground;
+    this.element.show();
+  },
+  triggerCallback: function(cbName, arg) {
+    if ('function' == typeof this.options[cbName]) {
+      this.options[cbName](this, arg);
+    }
+  },
+  unregisterListeners: function() {
+    $H(this._listeners).each(function(pair) {
+      if (!this.options.externalControlOnly)
+        this.element.stopObserving(pair.key, pair.value);
+      if (this.options.externalControl)
+        this.options.externalControl.stopObserving(pair.key, pair.value);
+    }.bind(this));
+  },
+  wrapUp: function(transport) {
+    this.leaveEditMode();
+    // Can't use triggerCallback due to backward compatibility: requires
+    // binding + direct element
+    this._boundComplete(transport, this.element);
+  }
+});
+
+Object.extend(Ajax.InPlaceEditor.prototype, {
+  dispose: Ajax.InPlaceEditor.prototype.destroy
+});
+
+Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
+  initialize: function($super, element, url, options) {
+    this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
+    $super(element, url, options);
+  },
+
+  createEditField: function() {
+    var list = document.createElement('select');
+    list.name = this.options.paramName;
+    list.size = 1;
+    this._controls.editor = list;
+    this._collection = this.options.collection || [];
+    if (this.options.loadCollectionURL)
+      this.loadCollection();
+    else
+      this.checkForExternalText();
+    this._form.appendChild(this._controls.editor);
+  },
+
+  loadCollection: function() {
+    this._form.addClassName(this.options.loadingClassName);
+    this.showLoadingText(this.options.loadingCollectionText);
+    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+    Object.extend(options, {
+      parameters: 'editorId=' + encodeURIComponent(this.element.id),
+      onComplete: Prototype.emptyFunction,
+      onSuccess: function(transport) {
+        var js = transport.responseText.strip();
+        if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+          throw 'Server returned an invalid collection representation.';
+        this._collection = eval(js);
+        this.checkForExternalText();
+      }.bind(this),
+      onFailure: this.onFailure
+    });
+    new Ajax.Request(this.options.loadCollectionURL, options);
+  },
+
+  showLoadingText: function(text) {
+    this._controls.editor.disabled = true;
+    var tempOption = this._controls.editor.firstChild;
+    if (!tempOption) {
+      tempOption = document.createElement('option');
+      tempOption.value = '';
+      this._controls.editor.appendChild(tempOption);
+      tempOption.selected = true;
+    }
+    tempOption.update((text || '').stripScripts().stripTags());
+  },
+
+  checkForExternalText: function() {
+    this._text = this.getText();
+    if (this.options.loadTextURL)
+      this.loadExternalText();
+    else
+      this.buildOptionList();
+  },
+
+  loadExternalText: function() {
+    this.showLoadingText(this.options.loadingText);
+    var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
+    Object.extend(options, {
+      parameters: 'editorId=' + encodeURIComponent(this.element.id),
+      onComplete: Prototype.emptyFunction,
+      onSuccess: function(transport) {
+        this._text = transport.responseText.strip();
+        this.buildOptionList();
+      }.bind(this),
+      onFailure: this.onFailure
+    });
+    new Ajax.Request(this.options.loadTextURL, options);
+  },
+
+  buildOptionList: function() {
+    this._form.removeClassName(this.options.loadingClassName);
+    this._collection = this._collection.map(function(entry) {
+      return 2 === entry.length ? entry : [entry, entry].flatten();
+    });
+    var marker = ('value' in this.options) ? this.options.value : this._text;
+    var textFound = this._collection.any(function(entry) {
+      return entry[0] == marker;
+    }.bind(this));
+    this._controls.editor.update('');
+    var option;
+    this._collection.each(function(entry, index) {
+      option = document.createElement('option');
+      option.value = entry[0];
+      option.selected = textFound ? entry[0] == marker : 0 == index;
+      option.appendChild(document.createTextNode(entry[1]));
+      this._controls.editor.appendChild(option);
+    }.bind(this));
+    this._controls.editor.disabled = false;
+    Field.scrollFreeActivate(this._controls.editor);
+  }
+});
+
+//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
+//**** This only  exists for a while,  in order to  let ****
+//**** users adapt to  the new API.  Read up on the new ****
+//**** API and convert your code to it ASAP!            ****
+
+Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
+  if (!options) return;
+  function fallback(name, expr) {
+    if (name in options || expr === undefined) return;
+    options[name] = expr;
+  };
+  fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
+    options.cancelLink == options.cancelButton == false ? false : undefined)));
+  fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
+    options.okLink == options.okButton == false ? false : undefined)));
+  fallback('highlightColor', options.highlightcolor);
+  fallback('highlightEndColor', options.highlightendcolor);
+};
+
+Object.extend(Ajax.InPlaceEditor, {
+  DefaultOptions: {
+    ajaxOptions: { },
+    autoRows: 3,                                // Use when multi-line w/ rows == 1
+    cancelControl: 'link',                      // 'link'|'button'|false
+    cancelText: 'cancel',
+    clickToEditText: 'Click to edit',
+    externalControl: null,                      // id|elt
+    externalControlOnly: false,
+    fieldPostCreation: 'activate',              // 'activate'|'focus'|false
+    formClassName: 'inplaceeditor-form',
+    formId: null,                               // id|elt
+    highlightColor: '#ffff99',
+    highlightEndColor: '#ffffff',
+    hoverClassName: '',
+    htmlResponse: true,
+    loadingClassName: 'inplaceeditor-loading',
+    loadingText: 'Loading...',
+    okControl: 'button',                        // 'link'|'button'|false
+    okText: 'ok',
+    paramName: 'value',
+    rows: 1,                                    // If 1 and multi-line, uses autoRows
+    savingClassName: 'inplaceeditor-saving',
+    savingText: 'Saving...',
+    size: 0,
+    stripLoadedTextTags: false,
+    submitOnBlur: false,
+    textAfterControls: '',
+    textBeforeControls: '',
+    textBetweenControls: ''
+  },
+  DefaultCallbacks: {
+    callback: function(form) {
+      return Form.serialize(form);
+    },
+    onComplete: function(transport, element) {
+      // For backward compatibility, this one is bound to the IPE, and passes
+      // the element directly.  It was too often customized, so we don't break it.
+      new Effect.Highlight(element, {
+        startcolor: this.options.highlightColor, keepBackgroundImage: true });
+    },
+    onEnterEditMode: null,
+    onEnterHover: function(ipe) {
+      ipe.element.style.backgroundColor = ipe.options.highlightColor;
+      if (ipe._effect)
+        ipe._effect.cancel();
+    },
+    onFailure: function(transport, ipe) {
+      alert('Error communication with the server: ' + transport.responseText.stripTags());
+    },
+    onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
+    onLeaveEditMode: null,
+    onLeaveHover: function(ipe) {
+      ipe._effect = new Effect.Highlight(ipe.element, {
+        startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
+        restorecolor: ipe._originalBackground, keepBackgroundImage: true
+      });
+    }
+  },
+  Listeners: {
+    click: 'enterEditMode',
+    keydown: 'checkForEscapeOrReturn',
+    mouseover: 'enterHover',
+    mouseout: 'leaveHover'
+  }
+});
+
+Ajax.InPlaceCollectionEditor.DefaultOptions = {
+  loadingCollectionText: 'Loading options...'
+};
+
+// Delayed observer, like Form.Element.Observer, 
+// but waits for delay after last key input
+// Ideal for live-search fields
+
+Form.Element.DelayedObserver = Class.create({
+  initialize: function(element, delay, callback) {
+    this.delay     = delay || 0.5;
+    this.element   = $(element);
+    this.callback  = callback;
+    this.timer     = null;
+    this.lastValue = $F(this.element); 
+    Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
+  },
+  delayedListener: function(event) {
+    if(this.lastValue == $F(this.element)) return;
+    if(this.timer) clearTimeout(this.timer);
+    this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
+    this.lastValue = $F(this.element);
+  },
+  onTimerEvent: function() {
+    this.timer = null;
+    this.callback(this.element, $F(this.element));
+  }
+});
Index: branches/features/taskProcedureRework/web-app/js/prototype/dragdrop.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/dragdrop.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/dragdrop.js	(revision 753)
@@ -0,0 +1,974 @@
+// script.aculo.us dragdrop.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005-2007 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
+// 
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if(Object.isUndefined(Effect))
+  throw("dragdrop.js requires including script.aculo.us' effects.js library");
+
+var Droppables = {
+  drops: [],
+
+  remove: function(element) {
+    this.drops = this.drops.reject(function(d) { return d.element==$(element) });
+  },
+
+  add: function(element) {
+    element = $(element);
+    var options = Object.extend({
+      greedy:     true,
+      hoverclass: null,
+      tree:       false
+    }, arguments[1] || { });
+
+    // cache containers
+    if(options.containment) {
+      options._containers = [];
+      var containment = options.containment;
+      if(Object.isArray(containment)) {
+        containment.each( function(c) { options._containers.push($(c)) });
+      } else {
+        options._containers.push($(containment));
+      }
+    }
+    
+    if(options.accept) options.accept = [options.accept].flatten();
+
+    Element.makePositioned(element); // fix IE
+    options.element = element;
+
+    this.drops.push(options);
+  },
+  
+  findDeepestChild: function(drops) {
+    deepest = drops[0];
+      
+    for (i = 1; i < drops.length; ++i)
+      if (Element.isParent(drops[i].element, deepest.element))
+        deepest = drops[i];
+    
+    return deepest;
+  },
+
+  isContained: function(element, drop) {
+    var containmentNode;
+    if(drop.tree) {
+      containmentNode = element.treeNode; 
+    } else {
+      containmentNode = element.parentNode;
+    }
+    return drop._containers.detect(function(c) { return containmentNode == c });
+  },
+  
+  isAffected: function(point, element, drop) {
+    return (
+      (drop.element!=element) &&
+      ((!drop._containers) ||
+        this.isContained(element, drop)) &&
+      ((!drop.accept) ||
+        (Element.classNames(element).detect( 
+          function(v) { return drop.accept.include(v) } ) )) &&
+      Position.within(drop.element, point[0], point[1]) );
+  },
+
+  deactivate: function(drop) {
+    if(drop.hoverclass)
+      Element.removeClassName(drop.element, drop.hoverclass);
+    this.last_active = null;
+  },
+
+  activate: function(drop) {
+    if(drop.hoverclass)
+      Element.addClassName(drop.element, drop.hoverclass);
+    this.last_active = drop;
+  },
+
+  show: function(point, element) {
+    if(!this.drops.length) return;
+    var drop, affected = [];
+    
+    this.drops.each( function(drop) {
+      if(Droppables.isAffected(point, element, drop))
+        affected.push(drop);
+    });
+        
+    if(affected.length>0)
+      drop = Droppables.findDeepestChild(affected);
+
+    if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
+    if (drop) {
+      Position.within(drop.element, point[0], point[1]);
+      if(drop.onHover)
+        drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
+      
+      if (drop != this.last_active) Droppables.activate(drop);
+    }
+  },
+
+  fire: function(event, element) {
+    if(!this.last_active) return;
+    Position.prepare();
+
+    if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
+      if (this.last_active.onDrop) {
+        this.last_active.onDrop(element, this.last_active.element, event); 
+        return true; 
+      }
+  },
+
+  reset: function() {
+    if(this.last_active)
+      this.deactivate(this.last_active);
+  }
+}
+
+var Draggables = {
+  drags: [],
+  observers: [],
+  
+  register: function(draggable) {
+    if(this.drags.length == 0) {
+      this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
+      this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
+      this.eventKeypress  = this.keyPress.bindAsEventListener(this);
+      
+      Event.observe(document, "mouseup", this.eventMouseUp);
+      Event.observe(document, "mousemove", this.eventMouseMove);
+      Event.observe(document, "keypress", this.eventKeypress);
+    }
+    this.drags.push(draggable);
+  },
+  
+  unregister: function(draggable) {
+    this.drags = this.drags.reject(function(d) { return d==draggable });
+    if(this.drags.length == 0) {
+      Event.stopObserving(document, "mouseup", this.eventMouseUp);
+      Event.stopObserving(document, "mousemove", this.eventMouseMove);
+      Event.stopObserving(document, "keypress", this.eventKeypress);
+    }
+  },
+  
+  activate: function(draggable) {
+    if(draggable.options.delay) { 
+      this._timeout = setTimeout(function() { 
+        Draggables._timeout = null; 
+        window.focus(); 
+        Draggables.activeDraggable = draggable; 
+      }.bind(this), draggable.options.delay); 
+    } else {
+      window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
+      this.activeDraggable = draggable;
+    }
+  },
+  
+  deactivate: function() {
+    this.activeDraggable = null;
+  },
+  
+  updateDrag: function(event) {
+    if(!this.activeDraggable) return;
+    var pointer = [Event.pointerX(event), Event.pointerY(event)];
+    // Mozilla-based browsers fire successive mousemove events with
+    // the same coordinates, prevent needless redrawing (moz bug?)
+    if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
+    this._lastPointer = pointer;
+    
+    this.activeDraggable.updateDrag(event, pointer);
+  },
+  
+  endDrag: function(event) {
+    if(this._timeout) { 
+      clearTimeout(this._timeout); 
+      this._timeout = null; 
+    }
+    if(!this.activeDraggable) return;
+    this._lastPointer = null;
+    this.activeDraggable.endDrag(event);
+    this.activeDraggable = null;
+  },
+  
+  keyPress: function(event) {
+    if(this.activeDraggable)
+      this.activeDraggable.keyPress(event);
+  },
+  
+  addObserver: function(observer) {
+    this.observers.push(observer);
+    this._cacheObserverCallbacks();
+  },
+  
+  removeObserver: function(element) {  // element instead of observer fixes mem leaks
+    this.observers = this.observers.reject( function(o) { return o.element==element });
+    this._cacheObserverCallbacks();
+  },
+  
+  notify: function(eventName, draggable, event) {  // 'onStart', 'onEnd', 'onDrag'
+    if(this[eventName+'Count'] > 0)
+      this.observers.each( function(o) {
+        if(o[eventName]) o[eventName](eventName, draggable, event);
+      });
+    if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
+  },
+  
+  _cacheObserverCallbacks: function() {
+    ['onStart','onEnd','onDrag'].each( function(eventName) {
+      Draggables[eventName+'Count'] = Draggables.observers.select(
+        function(o) { return o[eventName]; }
+      ).length;
+    });
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+var Draggable = Class.create({
+  initialize: function(element) {
+    var defaults = {
+      handle: false,
+      reverteffect: function(element, top_offset, left_offset) {
+        var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
+        new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
+          queue: {scope:'_draggable', position:'end'}
+        });
+      },
+      endeffect: function(element) {
+        var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
+        new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity, 
+          queue: {scope:'_draggable', position:'end'},
+          afterFinish: function(){ 
+            Draggable._dragging[element] = false 
+          }
+        }); 
+      },
+      zindex: 1000,
+      revert: false,
+      quiet: false,
+      scroll: false,
+      scrollSensitivity: 20,
+      scrollSpeed: 15,
+      snap: false,  // false, or xy or [x,y] or function(x,y){ return [x,y] }
+      delay: 0
+    };
+    
+    if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
+      Object.extend(defaults, {
+        starteffect: function(element) {
+          element._opacity = Element.getOpacity(element);
+          Draggable._dragging[element] = true;
+          new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); 
+        }
+      });
+    
+    var options = Object.extend(defaults, arguments[1] || { });
+
+    this.element = $(element);
+    
+    if(options.handle && Object.isString(options.handle))
+      this.handle = this.element.down('.'+options.handle, 0);
+    
+    if(!this.handle) this.handle = $(options.handle);
+    if(!this.handle) this.handle = this.element;
+    
+    if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+      options.scroll = $(options.scroll);
+      this._isScrollChild = Element.childOf(this.element, options.scroll);
+    }
+
+    Element.makePositioned(this.element); // fix IE    
+
+    this.options  = options;
+    this.dragging = false;   
+
+    this.eventMouseDown = this.initDrag.bindAsEventListener(this);
+    Event.observe(this.handle, "mousedown", this.eventMouseDown);
+    
+    Draggables.register(this);
+  },
+  
+  destroy: function() {
+    Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
+    Draggables.unregister(this);
+  },
+  
+  currentDelta: function() {
+    return([
+      parseInt(Element.getStyle(this.element,'left') || '0'),
+      parseInt(Element.getStyle(this.element,'top') || '0')]);
+  },
+  
+  initDrag: function(event) {
+    if(!Object.isUndefined(Draggable._dragging[this.element]) &&
+      Draggable._dragging[this.element]) return;
+    if(Event.isLeftClick(event)) {    
+      // abort on form elements, fixes a Firefox issue
+      var src = Event.element(event);
+      if((tag_name = src.tagName.toUpperCase()) && (
+        tag_name=='INPUT' ||
+        tag_name=='SELECT' ||
+        tag_name=='OPTION' ||
+        tag_name=='BUTTON' ||
+        tag_name=='TEXTAREA')) return;
+        
+      var pointer = [Event.pointerX(event), Event.pointerY(event)];
+      var pos     = Position.cumulativeOffset(this.element);
+      this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
+      
+      Draggables.activate(this);
+      Event.stop(event);
+    }
+  },
+  
+  startDrag: function(event) {
+    this.dragging = true;
+    if(!this.delta)
+      this.delta = this.currentDelta();
+    
+    if(this.options.zindex) {
+      this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+      this.element.style.zIndex = this.options.zindex;
+    }
+    
+    if(this.options.ghosting) {
+      this._clone = this.element.cloneNode(true);
+      this.element._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
+      if (!this.element._originallyAbsolute)
+        Position.absolutize(this.element);
+      this.element.parentNode.insertBefore(this._clone, this.element);
+    }
+    
+    if(this.options.scroll) {
+      if (this.options.scroll == window) {
+        var where = this._getWindowScroll(this.options.scroll);
+        this.originalScrollLeft = where.left;
+        this.originalScrollTop = where.top;
+      } else {
+        this.originalScrollLeft = this.options.scroll.scrollLeft;
+        this.originalScrollTop = this.options.scroll.scrollTop;
+      }
+    }
+    
+    Draggables.notify('onStart', this, event);
+        
+    if(this.options.starteffect) this.options.starteffect(this.element);
+  },
+  
+  updateDrag: function(event, pointer) {
+    if(!this.dragging) this.startDrag(event);
+    
+    if(!this.options.quiet){
+      Position.prepare();
+      Droppables.show(pointer, this.element);
+    }
+    
+    Draggables.notify('onDrag', this, event);
+    
+    this.draw(pointer);
+    if(this.options.change) this.options.change(this);
+    
+    if(this.options.scroll) {
+      this.stopScrolling();
+      
+      var p;
+      if (this.options.scroll == window) {
+        with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
+      } else {
+        p = Position.page(this.options.scroll);
+        p[0] += this.options.scroll.scrollLeft + Position.deltaX;
+        p[1] += this.options.scroll.scrollTop + Position.deltaY;
+        p.push(p[0]+this.options.scroll.offsetWidth);
+        p.push(p[1]+this.options.scroll.offsetHeight);
+      }
+      var speed = [0,0];
+      if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
+      if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
+      if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
+      if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
+      this.startScrolling(speed);
+    }
+    
+    // fix AppleWebKit rendering
+    if(Prototype.Browser.WebKit) window.scrollBy(0,0);
+    
+    Event.stop(event);
+  },
+  
+  finishDrag: function(event, success) {
+    this.dragging = false;
+    
+    if(this.options.quiet){
+      Position.prepare();
+      var pointer = [Event.pointerX(event), Event.pointerY(event)];
+      Droppables.show(pointer, this.element);
+    }
+
+    if(this.options.ghosting) {
+      if (!this.element._originallyAbsolute)
+        Position.relativize(this.element);
+      delete this.element._originallyAbsolute;
+      Element.remove(this._clone);
+      this._clone = null;
+    }
+
+    var dropped = false; 
+    if(success) { 
+      dropped = Droppables.fire(event, this.element); 
+      if (!dropped) dropped = false; 
+    }
+    if(dropped && this.options.onDropped) this.options.onDropped(this.element);
+    Draggables.notify('onEnd', this, event);
+
+    var revert = this.options.revert;
+    if(revert && Object.isFunction(revert)) revert = revert(this.element);
+    
+    var d = this.currentDelta();
+    if(revert && this.options.reverteffect) {
+      if (dropped == 0 || revert != 'failure')
+        this.options.reverteffect(this.element,
+          d[1]-this.delta[1], d[0]-this.delta[0]);
+    } else {
+      this.delta = d;
+    }
+
+    if(this.options.zindex)
+      this.element.style.zIndex = this.originalZ;
+
+    if(this.options.endeffect) 
+      this.options.endeffect(this.element);
+      
+    Draggables.deactivate(this);
+    Droppables.reset();
+  },
+  
+  keyPress: function(event) {
+    if(event.keyCode!=Event.KEY_ESC) return;
+    this.finishDrag(event, false);
+    Event.stop(event);
+  },
+  
+  endDrag: function(event) {
+    if(!this.dragging) return;
+    this.stopScrolling();
+    this.finishDrag(event, true);
+    Event.stop(event);
+  },
+  
+  draw: function(point) {
+    var pos = Position.cumulativeOffset(this.element);
+    if(this.options.ghosting) {
+      var r   = Position.realOffset(this.element);
+      pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
+    }
+    
+    var d = this.currentDelta();
+    pos[0] -= d[0]; pos[1] -= d[1];
+    
+    if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+      pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
+      pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
+    }
+    
+    var p = [0,1].map(function(i){ 
+      return (point[i]-pos[i]-this.offset[i]) 
+    }.bind(this));
+    
+    if(this.options.snap) {
+      if(Object.isFunction(this.options.snap)) {
+        p = this.options.snap(p[0],p[1],this);
+      } else {
+      if(Object.isArray(this.options.snap)) {
+        p = p.map( function(v, i) {
+          return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this))
+      } else {
+        p = p.map( function(v) {
+          return (v/this.options.snap).round()*this.options.snap }.bind(this))
+      }
+    }}
+    
+    var style = this.element.style;
+    if((!this.options.constraint) || (this.options.constraint=='horizontal'))
+      style.left = p[0] + "px";
+    if((!this.options.constraint) || (this.options.constraint=='vertical'))
+      style.top  = p[1] + "px";
+    
+    if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
+  },
+  
+  stopScrolling: function() {
+    if(this.scrollInterval) {
+      clearInterval(this.scrollInterval);
+      this.scrollInterval = null;
+      Draggables._lastScrollPointer = null;
+    }
+  },
+  
+  startScrolling: function(speed) {
+    if(!(speed[0] || speed[1])) return;
+    this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
+    this.lastScrolled = new Date();
+    this.scrollInterval = setInterval(this.scroll.bind(this), 10);
+  },
+  
+  scroll: function() {
+    var current = new Date();
+    var delta = current - this.lastScrolled;
+    this.lastScrolled = current;
+    if(this.options.scroll == window) {
+      with (this._getWindowScroll(this.options.scroll)) {
+        if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+          var d = delta / 1000;
+          this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
+        }
+      }
+    } else {
+      this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+      this.options.scroll.scrollTop  += this.scrollSpeed[1] * delta / 1000;
+    }
+    
+    Position.prepare();
+    Droppables.show(Draggables._lastPointer, this.element);
+    Draggables.notify('onDrag', this);
+    if (this._isScrollChild) {
+      Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
+      Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
+      Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
+      if (Draggables._lastScrollPointer[0] < 0)
+        Draggables._lastScrollPointer[0] = 0;
+      if (Draggables._lastScrollPointer[1] < 0)
+        Draggables._lastScrollPointer[1] = 0;
+      this.draw(Draggables._lastScrollPointer);
+    }
+    
+    if(this.options.change) this.options.change(this);
+  },
+  
+  _getWindowScroll: function(w) {
+    var T, L, W, H;
+    with (w.document) {
+      if (w.document.documentElement && documentElement.scrollTop) {
+        T = documentElement.scrollTop;
+        L = documentElement.scrollLeft;
+      } else if (w.document.body) {
+        T = body.scrollTop;
+        L = body.scrollLeft;
+      }
+      if (w.innerWidth) {
+        W = w.innerWidth;
+        H = w.innerHeight;
+      } else if (w.document.documentElement && documentElement.clientWidth) {
+        W = documentElement.clientWidth;
+        H = documentElement.clientHeight;
+      } else {
+        W = body.offsetWidth;
+        H = body.offsetHeight
+      }
+    }
+    return { top: T, left: L, width: W, height: H };
+  }
+});
+
+Draggable._dragging = { };
+
+/*--------------------------------------------------------------------------*/
+
+var SortableObserver = Class.create({
+  initialize: function(element, observer) {
+    this.element   = $(element);
+    this.observer  = observer;
+    this.lastValue = Sortable.serialize(this.element);
+  },
+  
+  onStart: function() {
+    this.lastValue = Sortable.serialize(this.element);
+  },
+  
+  onEnd: function() {
+    Sortable.unmark();
+    if(this.lastValue != Sortable.serialize(this.element))
+      this.observer(this.element)
+  }
+});
+
+var Sortable = {
+  SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
+  
+  sortables: { },
+  
+  _findRootElement: function(element) {
+    while (element.tagName.toUpperCase() != "BODY") {  
+      if(element.id && Sortable.sortables[element.id]) return element;
+      element = element.parentNode;
+    }
+  },
+
+  options: function(element) {
+    element = Sortable._findRootElement($(element));
+    if(!element) return;
+    return Sortable.sortables[element.id];
+  },
+  
+  destroy: function(element){
+    var s = Sortable.options(element);
+    
+    if(s) {
+      Draggables.removeObserver(s.element);
+      s.droppables.each(function(d){ Droppables.remove(d) });
+      s.draggables.invoke('destroy');
+      
+      delete Sortable.sortables[s.element.id];
+    }
+  },
+
+  create: function(element) {
+    element = $(element);
+    var options = Object.extend({ 
+      element:     element,
+      tag:         'li',       // assumes li children, override with tag: 'tagname'
+      dropOnEmpty: false,
+      tree:        false,
+      treeTag:     'ul',
+      overlap:     'vertical', // one of 'vertical', 'horizontal'
+      constraint:  'vertical', // one of 'vertical', 'horizontal', false
+      containment: element,    // also takes array of elements (or id's); or false
+      handle:      false,      // or a CSS class
+      only:        false,
+      delay:       0,
+      hoverclass:  null,
+      ghosting:    false,
+      quiet:       false, 
+      scroll:      false,
+      scrollSensitivity: 20,
+      scrollSpeed: 15,
+      format:      this.SERIALIZE_RULE,
+      
+      // these take arrays of elements or ids and can be 
+      // used for better initialization performance
+      elements:    false,
+      handles:     false,
+      
+      onChange:    Prototype.emptyFunction,
+      onUpdate:    Prototype.emptyFunction
+    }, arguments[1] || { });
+
+    // clear any old sortable with same element
+    this.destroy(element);
+
+    // build options for the draggables
+    var options_for_draggable = {
+      revert:      true,
+      quiet:       options.quiet,
+      scroll:      options.scroll,
+      scrollSpeed: options.scrollSpeed,
+      scrollSensitivity: options.scrollSensitivity,
+      delay:       options.delay,
+      ghosting:    options.ghosting,
+      constraint:  options.constraint,
+      handle:      options.handle };
+
+    if(options.starteffect)
+      options_for_draggable.starteffect = options.starteffect;
+
+    if(options.reverteffect)
+      options_for_draggable.reverteffect = options.reverteffect;
+    else
+      if(options.ghosting) options_for_draggable.reverteffect = function(element) {
+        element.style.top  = 0;
+        element.style.left = 0;
+      };
+
+    if(options.endeffect)
+      options_for_draggable.endeffect = options.endeffect;
+
+    if(options.zindex)
+      options_for_draggable.zindex = options.zindex;
+
+    // build options for the droppables  
+    var options_for_droppable = {
+      overlap:     options.overlap,
+      containment: options.containment,
+      tree:        options.tree,
+      hoverclass:  options.hoverclass,
+      onHover:     Sortable.onHover
+    }
+    
+    var options_for_tree = {
+      onHover:      Sortable.onEmptyHover,
+      overlap:      options.overlap,
+      containment:  options.containment,
+      hoverclass:   options.hoverclass
+    }
+
+    // fix for gecko engine
+    Element.cleanWhitespace(element); 
+
+    options.draggables = [];
+    options.droppables = [];
+
+    // drop on empty handling
+    if(options.dropOnEmpty || options.tree) {
+      Droppables.add(element, options_for_tree);
+      options.droppables.push(element);
+    }
+
+    (options.elements || this.findElements(element, options) || []).each( function(e,i) {
+      var handle = options.handles ? $(options.handles[i]) :
+        (options.handle ? $(e).select('.' + options.handle)[0] : e); 
+      options.draggables.push(
+        new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
+      Droppables.add(e, options_for_droppable);
+      if(options.tree) e.treeNode = element;
+      options.droppables.push(e);      
+    });
+    
+    if(options.tree) {
+      (Sortable.findTreeElements(element, options) || []).each( function(e) {
+        Droppables.add(e, options_for_tree);
+        e.treeNode = element;
+        options.droppables.push(e);
+      });
+    }
+
+    // keep reference
+    this.sortables[element.id] = options;
+
+    // for onupdate
+    Draggables.addObserver(new SortableObserver(element, options.onUpdate));
+
+  },
+
+  // return all suitable-for-sortable elements in a guaranteed order
+  findElements: function(element, options) {
+    return Element.findChildren(
+      element, options.only, options.tree ? true : false, options.tag);
+  },
+  
+  findTreeElements: function(element, options) {
+    return Element.findChildren(
+      element, options.only, options.tree ? true : false, options.treeTag);
+  },
+
+  onHover: function(element, dropon, overlap) {
+    if(Element.isParent(dropon, element)) return;
+
+    if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
+      return;
+    } else if(overlap>0.5) {
+      Sortable.mark(dropon, 'before');
+      if(dropon.previousSibling != element) {
+        var oldParentNode = element.parentNode;
+        element.style.visibility = "hidden"; // fix gecko rendering
+        dropon.parentNode.insertBefore(element, dropon);
+        if(dropon.parentNode!=oldParentNode) 
+          Sortable.options(oldParentNode).onChange(element);
+        Sortable.options(dropon.parentNode).onChange(element);
+      }
+    } else {
+      Sortable.mark(dropon, 'after');
+      var nextElement = dropon.nextSibling || null;
+      if(nextElement != element) {
+        var oldParentNode = element.parentNode;
+        element.style.visibility = "hidden"; // fix gecko rendering
+        dropon.parentNode.insertBefore(element, nextElement);
+        if(dropon.parentNode!=oldParentNode) 
+          Sortable.options(oldParentNode).onChange(element);
+        Sortable.options(dropon.parentNode).onChange(element);
+      }
+    }
+  },
+  
+  onEmptyHover: function(element, dropon, overlap) {
+    var oldParentNode = element.parentNode;
+    var droponOptions = Sortable.options(dropon);
+        
+    if(!Element.isParent(dropon, element)) {
+      var index;
+      
+      var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
+      var child = null;
+            
+      if(children) {
+        var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+        
+        for (index = 0; index < children.length; index += 1) {
+          if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
+            offset -= Element.offsetSize (children[index], droponOptions.overlap);
+          } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+            child = index + 1 < children.length ? children[index + 1] : null;
+            break;
+          } else {
+            child = children[index];
+            break;
+          }
+        }
+      }
+      
+      dropon.insertBefore(element, child);
+      
+      Sortable.options(oldParentNode).onChange(element);
+      droponOptions.onChange(element);
+    }
+  },
+
+  unmark: function() {
+    if(Sortable._marker) Sortable._marker.hide();
+  },
+
+  mark: function(dropon, position) {
+    // mark on ghosting only
+    var sortable = Sortable.options(dropon.parentNode);
+    if(sortable && !sortable.ghosting) return; 
+
+    if(!Sortable._marker) {
+      Sortable._marker = 
+        ($('dropmarker') || Element.extend(document.createElement('DIV'))).
+          hide().addClassName('dropmarker').setStyle({position:'absolute'});
+      document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
+    }    
+    var offsets = Position.cumulativeOffset(dropon);
+    Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
+    
+    if(position=='after')
+      if(sortable.overlap == 'horizontal') 
+        Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
+      else
+        Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
+    
+    Sortable._marker.show();
+  },
+  
+  _tree: function(element, options, parent) {
+    var children = Sortable.findElements(element, options) || [];
+  
+    for (var i = 0; i < children.length; ++i) {
+      var match = children[i].id.match(options.format);
+
+      if (!match) continue;
+      
+      var child = {
+        id: encodeURIComponent(match ? match[1] : null),
+        element: element,
+        parent: parent,
+        children: [],
+        position: parent.children.length,
+        container: $(children[i]).down(options.treeTag)
+      }
+      
+      /* Get the element containing the children and recurse over it */
+      if (child.container)
+        this._tree(child.container, options, child)
+      
+      parent.children.push (child);
+    }
+
+    return parent; 
+  },
+
+  tree: function(element) {
+    element = $(element);
+    var sortableOptions = this.options(element);
+    var options = Object.extend({
+      tag: sortableOptions.tag,
+      treeTag: sortableOptions.treeTag,
+      only: sortableOptions.only,
+      name: element.id,
+      format: sortableOptions.format
+    }, arguments[1] || { });
+    
+    var root = {
+      id: null,
+      parent: null,
+      children: [],
+      container: element,
+      position: 0
+    }
+    
+    return Sortable._tree(element, options, root);
+  },
+
+  /* Construct a [i] index for a particular node */
+  _constructIndex: function(node) {
+    var index = '';
+    do {
+      if (node.id) index = '[' + node.position + ']' + index;
+    } while ((node = node.parent) != null);
+    return index;
+  },
+
+  sequence: function(element) {
+    element = $(element);
+    var options = Object.extend(this.options(element), arguments[1] || { });
+    
+    return $(this.findElements(element, options) || []).map( function(item) {
+      return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+    });
+  },
+
+  setSequence: function(element, new_sequence) {
+    element = $(element);
+    var options = Object.extend(this.options(element), arguments[2] || { });
+    
+    var nodeMap = { };
+    this.findElements(element, options).each( function(n) {
+        if (n.id.match(options.format))
+            nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
+        n.parentNode.removeChild(n);
+    });
+   
+    new_sequence.each(function(ident) {
+      var n = nodeMap[ident];
+      if (n) {
+        n[1].appendChild(n[0]);
+        delete nodeMap[ident];
+      }
+    });
+  },
+  
+  serialize: function(element) {
+    element = $(element);
+    var options = Object.extend(Sortable.options(element), arguments[1] || { });
+    var name = encodeURIComponent(
+      (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
+    
+    if (options.tree) {
+      return Sortable.tree(element, arguments[1]).children.map( function (item) {
+        return [name + Sortable._constructIndex(item) + "[id]=" + 
+                encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+      }).flatten().join('&');
+    } else {
+      return Sortable.sequence(element, arguments[1]).map( function(item) {
+        return name + "[]=" + encodeURIComponent(item);
+      }).join('&');
+    }
+  }
+}
+
+// Returns true if child is contained within element
+Element.isParent = function(child, element) {
+  if (!child.parentNode || child == element) return false;
+  if (child.parentNode == element) return true;
+  return Element.isParent(child.parentNode, element);
+}
+
+Element.findChildren = function(element, only, recursive, tagName) {   
+  if(!element.hasChildNodes()) return null;
+  tagName = tagName.toUpperCase();
+  if(only) only = [only].flatten();
+  var elements = [];
+  $A(element.childNodes).each( function(e) {
+    if(e.tagName && e.tagName.toUpperCase()==tagName &&
+      (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
+        elements.push(e);
+    if(recursive) {
+      var grandchildren = Element.findChildren(e, only, recursive, tagName);
+      if(grandchildren) elements.push(grandchildren);
+    }
+  });
+
+  return (elements.length>0 ? elements.flatten() : []);
+}
+
+Element.offsetSize = function (element, type) {
+  return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
+}
Index: branches/features/taskProcedureRework/web-app/js/prototype/effects.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/effects.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/effects.js	(revision 753)
@@ -0,0 +1,1122 @@
+// script.aculo.us effects.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// Contributors:
+//  Justin Palmer (http://encytemedia.com/)
+//  Mark Pilgrim (http://diveintomark.org/)
+//  Martin Bialasinki
+// 
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/ 
+
+// converts rgb() and #xxx to #xxxxxx format,  
+// returns self (or first argument) if not convertable  
+String.prototype.parseColor = function() {  
+  var color = '#';
+  if (this.slice(0,4) == 'rgb(') {  
+    var cols = this.slice(4,this.length-1).split(',');  
+    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);  
+  } else {  
+    if (this.slice(0,1) == '#') {  
+      if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();  
+      if (this.length==7) color = this.toLowerCase();  
+    }  
+  }  
+  return (color.length==7 ? color : (arguments[0] || this));  
+};
+
+/*--------------------------------------------------------------------------*/
+
+Element.collectTextNodes = function(element) {  
+  return $A($(element).childNodes).collect( function(node) {
+    return (node.nodeType==3 ? node.nodeValue : 
+      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
+  }).flatten().join('');
+};
+
+Element.collectTextNodesIgnoreClass = function(element, className) {  
+  return $A($(element).childNodes).collect( function(node) {
+    return (node.nodeType==3 ? node.nodeValue : 
+      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
+        Element.collectTextNodesIgnoreClass(node, className) : ''));
+  }).flatten().join('');
+};
+
+Element.setContentZoom = function(element, percent) {
+  element = $(element);  
+  element.setStyle({fontSize: (percent/100) + 'em'});   
+  if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+  return element;
+};
+
+Element.getInlineOpacity = function(element){
+  return $(element).style.opacity || '';
+};
+
+Element.forceRerendering = function(element) {
+  try {
+    element = $(element);
+    var n = document.createTextNode(' ');
+    element.appendChild(n);
+    element.removeChild(n);
+  } catch(e) { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Effect = {
+  _elementDoesNotExistError: {
+    name: 'ElementDoesNotExistError',
+    message: 'The specified DOM element does not exist, but is required for this effect to operate'
+  },
+  Transitions: {
+    linear: Prototype.K,
+    sinoidal: function(pos) {
+      return (-Math.cos(pos*Math.PI)/2) + 0.5;
+    },
+    reverse: function(pos) {
+      return 1-pos;
+    },
+    flicker: function(pos) {
+      var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+      return pos > 1 ? 1 : pos;
+    },
+    wobble: function(pos) {
+      return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+    },
+    pulse: function(pos, pulses) { 
+      pulses = pulses || 5; 
+      return (
+        ((pos % (1/pulses)) * pulses).round() == 0 ? 
+              ((pos * pulses * 2) - (pos * pulses * 2).floor()) : 
+          1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
+        );
+    },
+    spring: function(pos) { 
+      return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); 
+    },
+    none: function(pos) {
+      return 0;
+    },
+    full: function(pos) {
+      return 1;
+    }
+  },
+  DefaultOptions: {
+    duration:   1.0,   // seconds
+    fps:        100,   // 100= assume 66fps max.
+    sync:       false, // true for combining
+    from:       0.0,
+    to:         1.0,
+    delay:      0.0,
+    queue:      'parallel'
+  },
+  tagifyText: function(element) {
+    var tagifyStyle = 'position:relative';
+    if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
+    
+    element = $(element);
+    $A(element.childNodes).each( function(child) {
+      if (child.nodeType==3) {
+        child.nodeValue.toArray().each( function(character) {
+          element.insertBefore(
+            new Element('span', {style: tagifyStyle}).update(
+              character == ' ' ? String.fromCharCode(160) : character), 
+              child);
+        });
+        Element.remove(child);
+      }
+    });
+  },
+  multiple: function(element, effect) {
+    var elements;
+    if (((typeof element == 'object') || 
+        Object.isFunction(element)) && 
+       (element.length))
+      elements = element;
+    else
+      elements = $(element).childNodes;
+      
+    var options = Object.extend({
+      speed: 0.1,
+      delay: 0.0
+    }, arguments[2] || { });
+    var masterDelay = options.delay;
+
+    $A(elements).each( function(element, index) {
+      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
+    });
+  },
+  PAIRS: {
+    'slide':  ['SlideDown','SlideUp'],
+    'blind':  ['BlindDown','BlindUp'],
+    'appear': ['Appear','Fade']
+  },
+  toggle: function(element, effect) {
+    element = $(element);
+    effect = (effect || 'appear').toLowerCase();
+    var options = Object.extend({
+      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
+    }, arguments[2] || { });
+    Effect[element.visible() ? 
+      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
+  }
+};
+
+Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
+
+/* ------------- core effects ------------- */
+
+Effect.ScopedQueue = Class.create(Enumerable, {
+  initialize: function() {
+    this.effects  = [];
+    this.interval = null;    
+  },
+  _each: function(iterator) {
+    this.effects._each(iterator);
+  },
+  add: function(effect) {
+    var timestamp = new Date().getTime();
+    
+    var position = Object.isString(effect.options.queue) ? 
+      effect.options.queue : effect.options.queue.position;
+    
+    switch(position) {
+      case 'front':
+        // move unstarted effects after this effect  
+        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
+            e.startOn  += effect.finishOn;
+            e.finishOn += effect.finishOn;
+          });
+        break;
+      case 'with-last':
+        timestamp = this.effects.pluck('startOn').max() || timestamp;
+        break;
+      case 'end':
+        // start effect after last queued effect has finished
+        timestamp = this.effects.pluck('finishOn').max() || timestamp;
+        break;
+    }
+    
+    effect.startOn  += timestamp;
+    effect.finishOn += timestamp;
+
+    if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
+      this.effects.push(effect);
+    
+    if (!this.interval)
+      this.interval = setInterval(this.loop.bind(this), 15);
+  },
+  remove: function(effect) {
+    this.effects = this.effects.reject(function(e) { return e==effect });
+    if (this.effects.length == 0) {
+      clearInterval(this.interval);
+      this.interval = null;
+    }
+  },
+  loop: function() {
+    var timePos = new Date().getTime();
+    for(var i=0, len=this.effects.length;i<len;i++) 
+      this.effects[i] && this.effects[i].loop(timePos);
+  }
+});
+
+Effect.Queues = {
+  instances: $H(),
+  get: function(queueName) {
+    if (!Object.isString(queueName)) return queueName;
+    
+    return this.instances.get(queueName) ||
+      this.instances.set(queueName, new Effect.ScopedQueue());
+  }
+};
+Effect.Queue = Effect.Queues.get('global');
+
+Effect.Base = Class.create({
+  position: null,
+  start: function(options) {
+    function codeForEvent(options,eventName){
+      return (
+        (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
+        (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
+      );
+    }
+    if (options && options.transition === false) options.transition = Effect.Transitions.linear;
+    this.options      = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
+    this.currentFrame = 0;
+    this.state        = 'idle';
+    this.startOn      = this.options.delay*1000;
+    this.finishOn     = this.startOn+(this.options.duration*1000);
+    this.fromToDelta  = this.options.to-this.options.from;
+    this.totalTime    = this.finishOn-this.startOn;
+    this.totalFrames  = this.options.fps*this.options.duration;
+    
+    eval('this.render = function(pos){ '+
+      'if (this.state=="idle"){this.state="running";'+
+      codeForEvent(this.options,'beforeSetup')+
+      (this.setup ? 'this.setup();':'')+ 
+      codeForEvent(this.options,'afterSetup')+
+      '};if (this.state=="running"){'+
+      'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
+      'this.position=pos;'+
+      codeForEvent(this.options,'beforeUpdate')+
+      (this.update ? 'this.update(pos);':'')+
+      codeForEvent(this.options,'afterUpdate')+
+      '}}');
+    
+    this.event('beforeStart');
+    if (!this.options.sync)
+      Effect.Queues.get(Object.isString(this.options.queue) ? 
+        'global' : this.options.queue.scope).add(this);
+  },
+  loop: function(timePos) {
+    if (timePos >= this.startOn) {
+      if (timePos >= this.finishOn) {
+        this.render(1.0);
+        this.cancel();
+        this.event('beforeFinish');
+        if (this.finish) this.finish(); 
+        this.event('afterFinish');
+        return;  
+      }
+      var pos   = (timePos - this.startOn) / this.totalTime,
+          frame = (pos * this.totalFrames).round();
+      if (frame > this.currentFrame) {
+        this.render(pos);
+        this.currentFrame = frame;
+      }
+    }
+  },
+  cancel: function() {
+    if (!this.options.sync)
+      Effect.Queues.get(Object.isString(this.options.queue) ? 
+        'global' : this.options.queue.scope).remove(this);
+    this.state = 'finished';
+  },
+  event: function(eventName) {
+    if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
+    if (this.options[eventName]) this.options[eventName](this);
+  },
+  inspect: function() {
+    var data = $H();
+    for(property in this)
+      if (!Object.isFunction(this[property])) data.set(property, this[property]);
+    return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
+  }
+});
+
+Effect.Parallel = Class.create(Effect.Base, {
+  initialize: function(effects) {
+    this.effects = effects || [];
+    this.start(arguments[1]);
+  },
+  update: function(position) {
+    this.effects.invoke('render', position);
+  },
+  finish: function(position) {
+    this.effects.each( function(effect) {
+      effect.render(1.0);
+      effect.cancel();
+      effect.event('beforeFinish');
+      if (effect.finish) effect.finish(position);
+      effect.event('afterFinish');
+    });
+  }
+});
+
+Effect.Tween = Class.create(Effect.Base, {
+  initialize: function(object, from, to) {
+    object = Object.isString(object) ? $(object) : object;
+    var args = $A(arguments), method = args.last(), 
+      options = args.length == 5 ? args[3] : null;
+    this.method = Object.isFunction(method) ? method.bind(object) :
+      Object.isFunction(object[method]) ? object[method].bind(object) : 
+      function(value) { object[method] = value };
+    this.start(Object.extend({ from: from, to: to }, options || { }));
+  },
+  update: function(position) {
+    this.method(position);
+  }
+});
+
+Effect.Event = Class.create(Effect.Base, {
+  initialize: function() {
+    this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
+  },
+  update: Prototype.emptyFunction
+});
+
+Effect.Opacity = Class.create(Effect.Base, {
+  initialize: function(element) {
+    this.element = $(element);
+    if (!this.element) throw(Effect._elementDoesNotExistError);
+    // make this work on IE on elements without 'layout'
+    if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+      this.element.setStyle({zoom: 1});
+    var options = Object.extend({
+      from: this.element.getOpacity() || 0.0,
+      to:   1.0
+    }, arguments[1] || { });
+    this.start(options);
+  },
+  update: function(position) {
+    this.element.setOpacity(position);
+  }
+});
+
+Effect.Move = Class.create(Effect.Base, {
+  initialize: function(element) {
+    this.element = $(element);
+    if (!this.element) throw(Effect._elementDoesNotExistError);
+    var options = Object.extend({
+      x:    0,
+      y:    0,
+      mode: 'relative'
+    }, arguments[1] || { });
+    this.start(options);
+  },
+  setup: function() {
+    this.element.makePositioned();
+    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
+    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
+    if (this.options.mode == 'absolute') {
+      this.options.x = this.options.x - this.originalLeft;
+      this.options.y = this.options.y - this.originalTop;
+    }
+  },
+  update: function(position) {
+    this.element.setStyle({
+      left: (this.options.x  * position + this.originalLeft).round() + 'px',
+      top:  (this.options.y  * position + this.originalTop).round()  + 'px'
+    });
+  }
+});
+
+// for backwards compatibility
+Effect.MoveBy = function(element, toTop, toLeft) {
+  return new Effect.Move(element, 
+    Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
+};
+
+Effect.Scale = Class.create(Effect.Base, {
+  initialize: function(element, percent) {
+    this.element = $(element);
+    if (!this.element) throw(Effect._elementDoesNotExistError);
+    var options = Object.extend({
+      scaleX: true,
+      scaleY: true,
+      scaleContent: true,
+      scaleFromCenter: false,
+      scaleMode: 'box',        // 'box' or 'contents' or { } with provided values
+      scaleFrom: 100.0,
+      scaleTo:   percent
+    }, arguments[2] || { });
+    this.start(options);
+  },
+  setup: function() {
+    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+    this.elementPositioning = this.element.getStyle('position');
+    
+    this.originalStyle = { };
+    ['top','left','width','height','fontSize'].each( function(k) {
+      this.originalStyle[k] = this.element.style[k];
+    }.bind(this));
+      
+    this.originalTop  = this.element.offsetTop;
+    this.originalLeft = this.element.offsetLeft;
+    
+    var fontSize = this.element.getStyle('font-size') || '100%';
+    ['em','px','%','pt'].each( function(fontSizeType) {
+      if (fontSize.indexOf(fontSizeType)>0) {
+        this.fontSize     = parseFloat(fontSize);
+        this.fontSizeType = fontSizeType;
+      }
+    }.bind(this));
+    
+    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+    
+    this.dims = null;
+    if (this.options.scaleMode=='box')
+      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+    if (/^content/.test(this.options.scaleMode))
+      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+    if (!this.dims)
+      this.dims = [this.options.scaleMode.originalHeight,
+                   this.options.scaleMode.originalWidth];
+  },
+  update: function(position) {
+    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
+    if (this.options.scaleContent && this.fontSize)
+      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
+    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
+  },
+  finish: function(position) {
+    if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
+  },
+  setDimensions: function(height, width) {
+    var d = { };
+    if (this.options.scaleX) d.width = width.round() + 'px';
+    if (this.options.scaleY) d.height = height.round() + 'px';
+    if (this.options.scaleFromCenter) {
+      var topd  = (height - this.dims[0])/2;
+      var leftd = (width  - this.dims[1])/2;
+      if (this.elementPositioning == 'absolute') {
+        if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
+        if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
+      } else {
+        if (this.options.scaleY) d.top = -topd + 'px';
+        if (this.options.scaleX) d.left = -leftd + 'px';
+      }
+    }
+    this.element.setStyle(d);
+  }
+});
+
+Effect.Highlight = Class.create(Effect.Base, {
+  initialize: function(element) {
+    this.element = $(element);
+    if (!this.element) throw(Effect._elementDoesNotExistError);
+    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
+    this.start(options);
+  },
+  setup: function() {
+    // Prevent executing on elements not in the layout flow
+    if (this.element.getStyle('display')=='none') { this.cancel(); return; }
+    // Disable background image during the effect
+    this.oldStyle = { };
+    if (!this.options.keepBackgroundImage) {
+      this.oldStyle.backgroundImage = this.element.getStyle('background-image');
+      this.element.setStyle({backgroundImage: 'none'});
+    }
+    if (!this.options.endcolor)
+      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
+    if (!this.options.restorecolor)
+      this.options.restorecolor = this.element.getStyle('background-color');
+    // init color calculations
+    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
+    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
+  },
+  update: function(position) {
+    this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
+      return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
+  },
+  finish: function() {
+    this.element.setStyle(Object.extend(this.oldStyle, {
+      backgroundColor: this.options.restorecolor
+    }));
+  }
+});
+
+Effect.ScrollTo = function(element) {
+  var options = arguments[1] || { },
+    scrollOffsets = document.viewport.getScrollOffsets(),
+    elementOffsets = $(element).cumulativeOffset(),
+    max = (window.height || document.body.scrollHeight) - document.viewport.getHeight();  
+
+  if (options.offset) elementOffsets[1] += options.offset;
+
+  return new Effect.Tween(null,
+    scrollOffsets.top,
+    elementOffsets[1] > max ? max : elementOffsets[1],
+    options,
+    function(p){ scrollTo(scrollOffsets.left, p.round()) }
+  );
+};
+
+/* ------------- combination effects ------------- */
+
+Effect.Fade = function(element) {
+  element = $(element);
+  var oldOpacity = element.getInlineOpacity();
+  var options = Object.extend({
+    from: element.getOpacity() || 1.0,
+    to:   0.0,
+    afterFinishInternal: function(effect) { 
+      if (effect.options.to!=0) return;
+      effect.element.hide().setStyle({opacity: oldOpacity}); 
+    }
+  }, arguments[1] || { });
+  return new Effect.Opacity(element,options);
+};
+
+Effect.Appear = function(element) {
+  element = $(element);
+  var options = Object.extend({
+  from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
+  to:   1.0,
+  // force Safari to render floated elements properly
+  afterFinishInternal: function(effect) {
+    effect.element.forceRerendering();
+  },
+  beforeSetup: function(effect) {
+    effect.element.setOpacity(effect.options.from).show(); 
+  }}, arguments[1] || { });
+  return new Effect.Opacity(element,options);
+};
+
+Effect.Puff = function(element) {
+  element = $(element);
+  var oldStyle = { 
+    opacity: element.getInlineOpacity(), 
+    position: element.getStyle('position'),
+    top:  element.style.top,
+    left: element.style.left,
+    width: element.style.width,
+    height: element.style.height
+  };
+  return new Effect.Parallel(
+   [ new Effect.Scale(element, 200, 
+      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), 
+     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], 
+     Object.extend({ duration: 1.0, 
+      beforeSetupInternal: function(effect) {
+        Position.absolutize(effect.effects[0].element)
+      },
+      afterFinishInternal: function(effect) {
+         effect.effects[0].element.hide().setStyle(oldStyle); }
+     }, arguments[1] || { })
+   );
+};
+
+Effect.BlindUp = function(element) {
+  element = $(element);
+  element.makeClipping();
+  return new Effect.Scale(element, 0,
+    Object.extend({ scaleContent: false, 
+      scaleX: false, 
+      restoreAfterFinish: true,
+      afterFinishInternal: function(effect) {
+        effect.element.hide().undoClipping();
+      } 
+    }, arguments[1] || { })
+  );
+};
+
+Effect.BlindDown = function(element) {
+  element = $(element);
+  var elementDimensions = element.getDimensions();
+  return new Effect.Scale(element, 100, Object.extend({ 
+    scaleContent: false, 
+    scaleX: false,
+    scaleFrom: 0,
+    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+    restoreAfterFinish: true,
+    afterSetup: function(effect) {
+      effect.element.makeClipping().setStyle({height: '0px'}).show(); 
+    },  
+    afterFinishInternal: function(effect) {
+      effect.element.undoClipping();
+    }
+  }, arguments[1] || { }));
+};
+
+Effect.SwitchOff = function(element) {
+  element = $(element);
+  var oldOpacity = element.getInlineOpacity();
+  return new Effect.Appear(element, Object.extend({
+    duration: 0.4,
+    from: 0,
+    transition: Effect.Transitions.flicker,
+    afterFinishInternal: function(effect) {
+      new Effect.Scale(effect.element, 1, { 
+        duration: 0.3, scaleFromCenter: true,
+        scaleX: false, scaleContent: false, restoreAfterFinish: true,
+        beforeSetup: function(effect) { 
+          effect.element.makePositioned().makeClipping();
+        },
+        afterFinishInternal: function(effect) {
+          effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
+        }
+      })
+    }
+  }, arguments[1] || { }));
+};
+
+Effect.DropOut = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.getStyle('top'),
+    left: element.getStyle('left'),
+    opacity: element.getInlineOpacity() };
+  return new Effect.Parallel(
+    [ new Effect.Move(element, {x: 0, y: 100, sync: true }), 
+      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
+    Object.extend(
+      { duration: 0.5,
+        beforeSetup: function(effect) {
+          effect.effects[0].element.makePositioned(); 
+        },
+        afterFinishInternal: function(effect) {
+          effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
+        } 
+      }, arguments[1] || { }));
+};
+
+Effect.Shake = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    distance: 20,
+    duration: 0.5
+  }, arguments[1] || {});
+  var distance = parseFloat(options.distance);
+  var split = parseFloat(options.duration) / 10.0;
+  var oldStyle = {
+    top: element.getStyle('top'),
+    left: element.getStyle('left') };
+    return new Effect.Move(element,
+      { x:  distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x:  distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x:  distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
+    new Effect.Move(effect.element,
+      { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
+        effect.element.undoPositioned().setStyle(oldStyle);
+  }}) }}) }}) }}) }}) }});
+};
+
+Effect.SlideDown = function(element) {
+  element = $(element).cleanWhitespace();
+  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
+  var oldInnerBottom = element.down().getStyle('bottom');
+  var elementDimensions = element.getDimensions();
+  return new Effect.Scale(element, 100, Object.extend({ 
+    scaleContent: false, 
+    scaleX: false, 
+    scaleFrom: window.opera ? 0 : 1,
+    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+    restoreAfterFinish: true,
+    afterSetup: function(effect) {
+      effect.element.makePositioned();
+      effect.element.down().makePositioned();
+      if (window.opera) effect.element.setStyle({top: ''});
+      effect.element.makeClipping().setStyle({height: '0px'}).show(); 
+    },
+    afterUpdateInternal: function(effect) {
+      effect.element.down().setStyle({bottom:
+        (effect.dims[0] - effect.element.clientHeight) + 'px' }); 
+    },
+    afterFinishInternal: function(effect) {
+      effect.element.undoClipping().undoPositioned();
+      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
+    }, arguments[1] || { })
+  );
+};
+
+Effect.SlideUp = function(element) {
+  element = $(element).cleanWhitespace();
+  var oldInnerBottom = element.down().getStyle('bottom');
+  var elementDimensions = element.getDimensions();
+  return new Effect.Scale(element, window.opera ? 0 : 1,
+   Object.extend({ scaleContent: false, 
+    scaleX: false, 
+    scaleMode: 'box',
+    scaleFrom: 100,
+    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
+    restoreAfterFinish: true,
+    afterSetup: function(effect) {
+      effect.element.makePositioned();
+      effect.element.down().makePositioned();
+      if (window.opera) effect.element.setStyle({top: ''});
+      effect.element.makeClipping().show();
+    },  
+    afterUpdateInternal: function(effect) {
+      effect.element.down().setStyle({bottom:
+        (effect.dims[0] - effect.element.clientHeight) + 'px' });
+    },
+    afterFinishInternal: function(effect) {
+      effect.element.hide().undoClipping().undoPositioned();
+      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
+    }
+   }, arguments[1] || { })
+  );
+};
+
+// Bug in opera makes the TD containing this element expand for a instance after finish 
+Effect.Squish = function(element) {
+  return new Effect.Scale(element, window.opera ? 1 : 0, { 
+    restoreAfterFinish: true,
+    beforeSetup: function(effect) {
+      effect.element.makeClipping(); 
+    },  
+    afterFinishInternal: function(effect) {
+      effect.element.hide().undoClipping(); 
+    }
+  });
+};
+
+Effect.Grow = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    direction: 'center',
+    moveTransition: Effect.Transitions.sinoidal,
+    scaleTransition: Effect.Transitions.sinoidal,
+    opacityTransition: Effect.Transitions.full
+  }, arguments[1] || { });
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    height: element.style.height,
+    width: element.style.width,
+    opacity: element.getInlineOpacity() };
+
+  var dims = element.getDimensions();    
+  var initialMoveX, initialMoveY;
+  var moveX, moveY;
+  
+  switch (options.direction) {
+    case 'top-left':
+      initialMoveX = initialMoveY = moveX = moveY = 0; 
+      break;
+    case 'top-right':
+      initialMoveX = dims.width;
+      initialMoveY = moveY = 0;
+      moveX = -dims.width;
+      break;
+    case 'bottom-left':
+      initialMoveX = moveX = 0;
+      initialMoveY = dims.height;
+      moveY = -dims.height;
+      break;
+    case 'bottom-right':
+      initialMoveX = dims.width;
+      initialMoveY = dims.height;
+      moveX = -dims.width;
+      moveY = -dims.height;
+      break;
+    case 'center':
+      initialMoveX = dims.width / 2;
+      initialMoveY = dims.height / 2;
+      moveX = -dims.width / 2;
+      moveY = -dims.height / 2;
+      break;
+  }
+  
+  return new Effect.Move(element, {
+    x: initialMoveX,
+    y: initialMoveY,
+    duration: 0.01, 
+    beforeSetup: function(effect) {
+      effect.element.hide().makeClipping().makePositioned();
+    },
+    afterFinishInternal: function(effect) {
+      new Effect.Parallel(
+        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
+          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
+          new Effect.Scale(effect.element, 100, {
+            scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 
+            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
+        ], Object.extend({
+             beforeSetup: function(effect) {
+               effect.effects[0].element.setStyle({height: '0px'}).show(); 
+             },
+             afterFinishInternal: function(effect) {
+               effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); 
+             }
+           }, options)
+      )
+    }
+  });
+};
+
+Effect.Shrink = function(element) {
+  element = $(element);
+  var options = Object.extend({
+    direction: 'center',
+    moveTransition: Effect.Transitions.sinoidal,
+    scaleTransition: Effect.Transitions.sinoidal,
+    opacityTransition: Effect.Transitions.none
+  }, arguments[1] || { });
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    height: element.style.height,
+    width: element.style.width,
+    opacity: element.getInlineOpacity() };
+
+  var dims = element.getDimensions();
+  var moveX, moveY;
+  
+  switch (options.direction) {
+    case 'top-left':
+      moveX = moveY = 0;
+      break;
+    case 'top-right':
+      moveX = dims.width;
+      moveY = 0;
+      break;
+    case 'bottom-left':
+      moveX = 0;
+      moveY = dims.height;
+      break;
+    case 'bottom-right':
+      moveX = dims.width;
+      moveY = dims.height;
+      break;
+    case 'center':  
+      moveX = dims.width / 2;
+      moveY = dims.height / 2;
+      break;
+  }
+  
+  return new Effect.Parallel(
+    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
+      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
+      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
+    ], Object.extend({            
+         beforeStartInternal: function(effect) {
+           effect.effects[0].element.makePositioned().makeClipping(); 
+         },
+         afterFinishInternal: function(effect) {
+           effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
+       }, options)
+  );
+};
+
+Effect.Pulsate = function(element) {
+  element = $(element);
+  var options    = arguments[1] || { };
+  var oldOpacity = element.getInlineOpacity();
+  var transition = options.transition || Effect.Transitions.sinoidal;
+  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
+  reverser.bind(transition);
+  return new Effect.Opacity(element, 
+    Object.extend(Object.extend({  duration: 2.0, from: 0,
+      afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
+    }, options), {transition: reverser}));
+};
+
+Effect.Fold = function(element) {
+  element = $(element);
+  var oldStyle = {
+    top: element.style.top,
+    left: element.style.left,
+    width: element.style.width,
+    height: element.style.height };
+  element.makeClipping();
+  return new Effect.Scale(element, 5, Object.extend({   
+    scaleContent: false,
+    scaleX: false,
+    afterFinishInternal: function(effect) {
+    new Effect.Scale(element, 1, { 
+      scaleContent: false, 
+      scaleY: false,
+      afterFinishInternal: function(effect) {
+        effect.element.hide().undoClipping().setStyle(oldStyle);
+      } });
+  }}, arguments[1] || { }));
+};
+
+Effect.Morph = Class.create(Effect.Base, {
+  initialize: function(element) {
+    this.element = $(element);
+    if (!this.element) throw(Effect._elementDoesNotExistError);
+    var options = Object.extend({
+      style: { }
+    }, arguments[1] || { });
+    
+    if (!Object.isString(options.style)) this.style = $H(options.style);
+    else {
+      if (options.style.include(':'))
+        this.style = options.style.parseStyle();
+      else {
+        this.element.addClassName(options.style);
+        this.style = $H(this.element.getStyles());
+        this.element.removeClassName(options.style);
+        var css = this.element.getStyles();
+        this.style = this.style.reject(function(style) {
+          return style.value == css[style.key];
+        });
+        options.afterFinishInternal = function(effect) {
+          effect.element.addClassName(effect.options.style);
+          effect.transforms.each(function(transform) {
+            effect.element.style[transform.style] = '';
+          });
+        }
+      }
+    }
+    this.start(options);
+  },
+  
+  setup: function(){
+    function parseColor(color){
+      if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
+      color = color.parseColor();
+      return $R(0,2).map(function(i){
+        return parseInt( color.slice(i*2+1,i*2+3), 16 ) 
+      });
+    }
+    this.transforms = this.style.map(function(pair){
+      var property = pair[0], value = pair[1], unit = null;
+
+      if (value.parseColor('#zzzzzz') != '#zzzzzz') {
+        value = value.parseColor();
+        unit  = 'color';
+      } else if (property == 'opacity') {
+        value = parseFloat(value);
+        if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
+          this.element.setStyle({zoom: 1});
+      } else if (Element.CSS_LENGTH.test(value)) {
+          var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+          value = parseFloat(components[1]);
+          unit = (components.length == 3) ? components[2] : null;
+      }
+
+      var originalValue = this.element.getStyle(property);
+      return { 
+        style: property.camelize(), 
+        originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), 
+        targetValue: unit=='color' ? parseColor(value) : value,
+        unit: unit
+      };
+    }.bind(this)).reject(function(transform){
+      return (
+        (transform.originalValue == transform.targetValue) ||
+        (
+          transform.unit != 'color' &&
+          (isNaN(transform.originalValue) || isNaN(transform.targetValue))
+        )
+      )
+    });
+  },
+  update: function(position) {
+    var style = { }, transform, i = this.transforms.length;
+    while(i--)
+      style[(transform = this.transforms[i]).style] = 
+        transform.unit=='color' ? '#'+
+          (Math.round(transform.originalValue[0]+
+            (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
+          (Math.round(transform.originalValue[1]+
+            (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
+          (Math.round(transform.originalValue[2]+
+            (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
+        (transform.originalValue +
+          (transform.targetValue - transform.originalValue) * position).toFixed(3) + 
+            (transform.unit === null ? '' : transform.unit);
+    this.element.setStyle(style, true);
+  }
+});
+
+Effect.Transform = Class.create({
+  initialize: function(tracks){
+    this.tracks  = [];
+    this.options = arguments[1] || { };
+    this.addTracks(tracks);
+  },
+  addTracks: function(tracks){
+    tracks.each(function(track){
+      track = $H(track);
+      var data = track.values().first();
+      this.tracks.push($H({
+        ids:     track.keys().first(),
+        effect:  Effect.Morph,
+        options: { style: data }
+      }));
+    }.bind(this));
+    return this;
+  },
+  play: function(){
+    return new Effect.Parallel(
+      this.tracks.map(function(track){
+        var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
+        var elements = [$(ids) || $$(ids)].flatten();
+        return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
+      }).flatten(),
+      this.options
+    );
+  }
+});
+
+Element.CSS_PROPERTIES = $w(
+  'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 
+  'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
+  'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
+  'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
+  'fontSize fontWeight height left letterSpacing lineHeight ' +
+  'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
+  'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
+  'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
+  'right textIndent top width wordSpacing zIndex');
+  
+Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+String.__parseStyleElement = document.createElement('div');
+String.prototype.parseStyle = function(){
+  var style, styleRules = $H();
+  if (Prototype.Browser.WebKit)
+    style = new Element('div',{style:this}).style;
+  else {
+    String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
+    style = String.__parseStyleElement.childNodes[0].style;
+  }
+  
+  Element.CSS_PROPERTIES.each(function(property){
+    if (style[property]) styleRules.set(property, style[property]); 
+  });
+  
+  if (Prototype.Browser.IE && this.include('opacity'))
+    styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
+
+  return styleRules;
+};
+
+if (document.defaultView && document.defaultView.getComputedStyle) {
+  Element.getStyles = function(element) {
+    var css = document.defaultView.getComputedStyle($(element), null);
+    return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
+      styles[property] = css[property];
+      return styles;
+    });
+  };
+} else {
+  Element.getStyles = function(element) {
+    element = $(element);
+    var css = element.currentStyle, styles;
+    styles = Element.CSS_PROPERTIES.inject({ }, function(hash, property) {
+      hash.set(property, css[property]);
+      return hash;
+    });
+    if (!styles.opacity) styles.set('opacity', element.getOpacity());
+    return styles;
+  };
+};
+
+Effect.Methods = {
+  morph: function(element, style) {
+    element = $(element);
+    new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
+    return element;
+  },
+  visualEffect: function(element, effect, options) {
+    element = $(element)
+    var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
+    new Effect[klass](element, options);
+    return element;
+  },
+  highlight: function(element, options) {
+    element = $(element);
+    new Effect.Highlight(element, options);
+    return element;
+  }
+};
+
+$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
+  'pulsate shake puff squish switchOff dropOut').each(
+  function(effect) { 
+    Effect.Methods[effect] = function(element, options){
+      element = $(element);
+      Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
+      return element;
+    }
+  }
+);
+
+$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( 
+  function(f) { Effect.Methods[f] = Element[f]; }
+);
+
+Element.addMethods(Effect.Methods);
Index: branches/features/taskProcedureRework/web-app/js/prototype/prototype.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/prototype.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/prototype.js	(revision 753)
@@ -0,0 +1,4184 @@
+/*  Prototype JavaScript framework, version 1.6.0
+ *  (c) 2005-2007 Sam Stephenson
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+  Version: '1.6.0',
+
+  Browser: {
+    IE:     !!(window.attachEvent && !window.opera),
+    Opera:  !!window.opera,
+    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+    MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+  },
+
+  BrowserFeatures: {
+    XPath: !!document.evaluate,
+    ElementExtensions: !!window.HTMLElement,
+    SpecificElementExtensions:
+      document.createElement('div').__proto__ &&
+      document.createElement('div').__proto__ !==
+        document.createElement('form').__proto__
+  },
+
+  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+  emptyFunction: function() { },
+  K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+  Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+if (Prototype.Browser.WebKit)
+  Prototype.BrowserFeatures.XPath = false;
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+  create: function() {
+    var parent = null, properties = $A(arguments);
+    if (Object.isFunction(properties[0]))
+      parent = properties.shift();
+
+    function klass() {
+      this.initialize.apply(this, arguments);
+    }
+
+    Object.extend(klass, Class.Methods);
+    klass.superclass = parent;
+    klass.subclasses = [];
+
+    if (parent) {
+      var subclass = function() { };
+      subclass.prototype = parent.prototype;
+      klass.prototype = new subclass;
+      parent.subclasses.push(klass);
+    }
+
+    for (var i = 0; i < properties.length; i++)
+      klass.addMethods(properties[i]);
+
+    if (!klass.prototype.initialize)
+      klass.prototype.initialize = Prototype.emptyFunction;
+
+    klass.prototype.constructor = klass;
+
+    return klass;
+  }
+};
+
+Class.Methods = {
+  addMethods: function(source) {
+    var ancestor   = this.superclass && this.superclass.prototype;
+    var properties = Object.keys(source);
+
+    if (!Object.keys({ toString: true }).length)
+      properties.push("toString", "valueOf");
+
+    for (var i = 0, length = properties.length; i < length; i++) {
+      var property = properties[i], value = source[property];
+      if (ancestor && Object.isFunction(value) &&
+          value.argumentNames().first() == "$super") {
+        var method = value, value = Object.extend((function(m) {
+          return function() { return ancestor[m].apply(this, arguments) };
+        })(property).wrap(method), {
+          valueOf:  function() { return method },
+          toString: function() { return method.toString() }
+        });
+      }
+      this.prototype[property] = value;
+    }
+
+    return this;
+  }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+  for (var property in source)
+    destination[property] = source[property];
+  return destination;
+};
+
+Object.extend(Object, {
+  inspect: function(object) {
+    try {
+      if (object === undefined) return 'undefined';
+      if (object === null) return 'null';
+      return object.inspect ? object.inspect() : object.toString();
+    } catch (e) {
+      if (e instanceof RangeError) return '...';
+      throw e;
+    }
+  },
+
+  toJSON: function(object) {
+    var type = typeof object;
+    switch (type) {
+      case 'undefined':
+      case 'function':
+      case 'unknown': return;
+      case 'boolean': return object.toString();
+    }
+
+    if (object === null) return 'null';
+    if (object.toJSON) return object.toJSON();
+    if (Object.isElement(object)) return;
+
+    var results = [];
+    for (var property in object) {
+      var value = Object.toJSON(object[property]);
+      if (value !== undefined)
+        results.push(property.toJSON() + ': ' + value);
+    }
+
+    return '{' + results.join(', ') + '}';
+  },
+
+  toQueryString: function(object) {
+    return $H(object).toQueryString();
+  },
+
+  toHTML: function(object) {
+    return object && object.toHTML ? object.toHTML() : String.interpret(object);
+  },
+
+  keys: function(object) {
+    var keys = [];
+    for (var property in object)
+      keys.push(property);
+    return keys;
+  },
+
+  values: function(object) {
+    var values = [];
+    for (var property in object)
+      values.push(object[property]);
+    return values;
+  },
+
+  clone: function(object) {
+    return Object.extend({ }, object);
+  },
+
+  isElement: function(object) {
+    return object && object.nodeType == 1;
+  },
+
+  isArray: function(object) {
+    return object && object.constructor === Array;
+  },
+
+  isHash: function(object) {
+    return object instanceof Hash;
+  },
+
+  isFunction: function(object) {
+    return typeof object == "function";
+  },
+
+  isString: function(object) {
+    return typeof object == "string";
+  },
+
+  isNumber: function(object) {
+    return typeof object == "number";
+  },
+
+  isUndefined: function(object) {
+    return typeof object == "undefined";
+  }
+});
+
+Object.extend(Function.prototype, {
+  argumentNames: function() {
+    var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+    return names.length == 1 && !names[0] ? [] : names;
+  },
+
+  bind: function() {
+    if (arguments.length < 2 && arguments[0] === undefined) return this;
+    var __method = this, args = $A(arguments), object = args.shift();
+    return function() {
+      return __method.apply(object, args.concat($A(arguments)));
+    }
+  },
+
+  bindAsEventListener: function() {
+    var __method = this, args = $A(arguments), object = args.shift();
+    return function(event) {
+      return __method.apply(object, [event || window.event].concat(args));
+    }
+  },
+
+  curry: function() {
+    if (!arguments.length) return this;
+    var __method = this, args = $A(arguments);
+    return function() {
+      return __method.apply(this, args.concat($A(arguments)));
+    }
+  },
+
+  delay: function() {
+    var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+    return window.setTimeout(function() {
+      return __method.apply(__method, args);
+    }, timeout);
+  },
+
+  wrap: function(wrapper) {
+    var __method = this;
+    return function() {
+      return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+    }
+  },
+
+  methodize: function() {
+    if (this._methodized) return this._methodized;
+    var __method = this;
+    return this._methodized = function() {
+      return __method.apply(null, [this].concat($A(arguments)));
+    };
+  }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+  return '"' + this.getUTCFullYear() + '-' +
+    (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+    this.getUTCDate().toPaddedString(2) + 'T' +
+    this.getUTCHours().toPaddedString(2) + ':' +
+    this.getUTCMinutes().toPaddedString(2) + ':' +
+    this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+  these: function() {
+    var returnValue;
+
+    for (var i = 0, length = arguments.length; i < length; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) { }
+    }
+
+    return returnValue;
+  }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+  initialize: function(callback, frequency) {
+    this.callback = callback;
+    this.frequency = frequency;
+    this.currentlyExecuting = false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  execute: function() {
+    this.callback(this);
+  },
+
+  stop: function() {
+    if (!this.timer) return;
+    clearInterval(this.timer);
+    this.timer = null;
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try {
+        this.currentlyExecuting = true;
+        this.execute();
+      } finally {
+        this.currentlyExecuting = false;
+      }
+    }
+  }
+});
+Object.extend(String, {
+  interpret: function(value) {
+    return value == null ? '' : String(value);
+  },
+  specialChar: {
+    '\b': '\\b',
+    '\t': '\\t',
+    '\n': '\\n',
+    '\f': '\\f',
+    '\r': '\\r',
+    '\\': '\\\\'
+  }
+});
+
+Object.extend(String.prototype, {
+  gsub: function(pattern, replacement) {
+    var result = '', source = this, match;
+    replacement = arguments.callee.prepareReplacement(replacement);
+
+    while (source.length > 0) {
+      if (match = source.match(pattern)) {
+        result += source.slice(0, match.index);
+        result += String.interpret(replacement(match));
+        source  = source.slice(match.index + match[0].length);
+      } else {
+        result += source, source = '';
+      }
+    }
+    return result;
+  },
+
+  sub: function(pattern, replacement, count) {
+    replacement = this.gsub.prepareReplacement(replacement);
+    count = count === undefined ? 1 : count;
+
+    return this.gsub(pattern, function(match) {
+      if (--count < 0) return match[0];
+      return replacement(match);
+    });
+  },
+
+  scan: function(pattern, iterator) {
+    this.gsub(pattern, iterator);
+    return String(this);
+  },
+
+  truncate: function(length, truncation) {
+    length = length || 30;
+    truncation = truncation === undefined ? '...' : truncation;
+    return this.length > length ?
+      this.slice(0, length - truncation.length) + truncation : String(this);
+  },
+
+  strip: function() {
+    return this.replace(/^\s+/, '').replace(/\s+$/, '');
+  },
+
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  stripScripts: function() {
+    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+  },
+
+  extractScripts: function() {
+    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+    return (this.match(matchAll) || []).map(function(scriptTag) {
+      return (scriptTag.match(matchOne) || ['', ''])[1];
+    });
+  },
+
+  evalScripts: function() {
+    return this.extractScripts().map(function(script) { return eval(script) });
+  },
+
+  escapeHTML: function() {
+    var self = arguments.callee;
+    self.text.data = this;
+    return self.div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div = new Element('div');
+    div.innerHTML = this.stripTags();
+    return div.childNodes[0] ? (div.childNodes.length > 1 ?
+      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+      div.childNodes[0].nodeValue) : '';
+  },
+
+  toQueryParams: function(separator) {
+    var match = this.strip().match(/([^?#]*)(#.*)?$/);
+    if (!match) return { };
+
+    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+      if ((pair = pair.split('='))[0]) {
+        var key = decodeURIComponent(pair.shift());
+        var value = pair.length > 1 ? pair.join('=') : pair[0];
+        if (value != undefined) value = decodeURIComponent(value);
+
+        if (key in hash) {
+          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+          hash[key].push(value);
+        }
+        else hash[key] = value;
+      }
+      return hash;
+    });
+  },
+
+  toArray: function() {
+    return this.split('');
+  },
+
+  succ: function() {
+    return this.slice(0, this.length - 1) +
+      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+  },
+
+  times: function(count) {
+    return count < 1 ? '' : new Array(count + 1).join(this);
+  },
+
+  camelize: function() {
+    var parts = this.split('-'), len = parts.length;
+    if (len == 1) return parts[0];
+
+    var camelized = this.charAt(0) == '-'
+      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+      : parts[0];
+
+    for (var i = 1; i < len; i++)
+      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+    return camelized;
+  },
+
+  capitalize: function() {
+    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+  },
+
+  underscore: function() {
+    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+  },
+
+  dasherize: function() {
+    return this.gsub(/_/,'-');
+  },
+
+  inspect: function(useDoubleQuotes) {
+    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+      var character = String.specialChar[match[0]];
+      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+    });
+    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+  },
+
+  toJSON: function() {
+    return this.inspect(true);
+  },
+
+  unfilterJSON: function(filter) {
+    return this.sub(filter || Prototype.JSONFilter, '#{1}');
+  },
+
+  isJSON: function() {
+    var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+  },
+
+  evalJSON: function(sanitize) {
+    var json = this.unfilterJSON();
+    try {
+      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+    } catch (e) { }
+    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+  },
+
+  include: function(pattern) {
+    return this.indexOf(pattern) > -1;
+  },
+
+  startsWith: function(pattern) {
+    return this.indexOf(pattern) === 0;
+  },
+
+  endsWith: function(pattern) {
+    var d = this.length - pattern.length;
+    return d >= 0 && this.lastIndexOf(pattern) === d;
+  },
+
+  empty: function() {
+    return this == '';
+  },
+
+  blank: function() {
+    return /^\s*$/.test(this);
+  },
+
+  interpolate: function(object, pattern) {
+    return new Template(this, pattern).evaluate(object);
+  }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+  escapeHTML: function() {
+    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+  },
+  unescapeHTML: function() {
+    return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+  }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+  if (Object.isFunction(replacement)) return replacement;
+  var template = new Template(replacement);
+  return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+  div:  document.createElement('div'),
+  text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+  initialize: function(template, pattern) {
+    this.template = template.toString();
+    this.pattern = pattern || Template.Pattern;
+  },
+
+  evaluate: function(object) {
+    if (Object.isFunction(object.toTemplateReplacements))
+      object = object.toTemplateReplacements();
+
+    return this.template.gsub(this.pattern, function(match) {
+      if (object == null) return '';
+
+      var before = match[1] || '';
+      if (before == '\\') return match[2];
+
+      var ctx = object, expr = match[3];
+      var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr);
+      if (match == null) return before;
+
+      while (match != null) {
+        var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+        ctx = ctx[comp];
+        if (null == ctx || '' == match[3]) break;
+        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+        match = pattern.exec(expr);
+      }
+
+      return before + String.interpret(ctx);
+    }.bind(this));
+  }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+  each: function(iterator, context) {
+    var index = 0;
+    iterator = iterator.bind(context);
+    try {
+      this._each(function(value) {
+        iterator(value, index++);
+      });
+    } catch (e) {
+      if (e != $break) throw e;
+    }
+    return this;
+  },
+
+  eachSlice: function(number, iterator, context) {
+    iterator = iterator ? iterator.bind(context) : Prototype.K;
+    var index = -number, slices = [], array = this.toArray();
+    while ((index += number) < array.length)
+      slices.push(array.slice(index, index+number));
+    return slices.collect(iterator, context);
+  },
+
+  all: function(iterator, context) {
+    iterator = iterator ? iterator.bind(context) : Prototype.K;
+    var result = true;
+    this.each(function(value, index) {
+      result = result && !!iterator(value, index);
+      if (!result) throw $break;
+    });
+    return result;
+  },
+
+  any: function(iterator, context) {
+    iterator = iterator ? iterator.bind(context) : Prototype.K;
+    var result = false;
+    this.each(function(value, index) {
+      if (result = !!iterator(value, index))
+        throw $break;
+    });
+    return result;
+  },
+
+  collect: function(iterator, context) {
+    iterator = iterator ? iterator.bind(context) : Prototype.K;
+    var results = [];
+    this.each(function(value, index) {
+      results.push(iterator(value, index));
+    });
+    return results;
+  },
+
+  detect: function(iterator, context) {
+    iterator = iterator.bind(context);
+    var result;
+    this.each(function(value, index) {
+      if (iterator(value, index)) {
+        result = value;
+        throw $break;
+      }
+    });
+    return result;
+  },
+
+  findAll: function(iterator, context) {
+    iterator = iterator.bind(context);
+    var results = [];
+    this.each(function(value, index) {
+      if (iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  grep: function(filter, iterator, context) {
+    iterator = iterator ? iterator.bind(context) : Prototype.K;
+    var results = [];
+
+    if (Object.isString(filter))
+      filter = new RegExp(filter);
+
+    this.each(function(value, index) {
+      if (filter.match(value))
+        results.push(iterator(value, index));
+    });
+    return results;
+  },
+
+  include: function(object) {
+    if (Object.isFunction(this.indexOf))
+      if (this.indexOf(object) != -1) return true;
+
+    var found = false;
+    this.each(function(value) {
+      if (value == object) {
+        found = true;
+        throw $break;
+      }
+    });
+    return found;
+  },
+
+  inGroupsOf: function(number, fillWith) {
+    fillWith = fillWith === undefined ? null : fillWith;
+    return this.eachSlice(number, function(slice) {
+      while(slice.length < number) slice.push(fillWith);
+      return slice;
+    });
+  },
+
+  inject: function(memo, iterator, context) {
+    iterator = iterator.bind(context);
+    this.each(function(value, index) {
+      memo = iterator(memo, value, index);
+    });
+    return memo;
+  },
+
+  invoke: function(method) {
+    var args = $A(arguments).slice(1);
+    return this.map(function(value) {
+      return value[method].apply(value, args);
+    });
+  },
+
+  max: function(iterator, context) {
+    iterator = iterator ? iterator.bind(context) : Prototype.K;
+    var result;
+    this.each(function(value, index) {
+      value = iterator(value, index);
+      if (result == undefined || value >= result)
+        result = value;
+    });
+    return result;
+  },
+
+  min: function(iterator, context) {
+    iterator = iterator ? iterator.bind(context) : Prototype.K;
+    var result;
+    this.each(function(value, index) {
+      value = iterator(value, index);
+      if (result == undefined || value < result)
+        result = value;
+    });
+    return result;
+  },
+
+  partition: function(iterator, context) {
+    iterator = iterator ? iterator.bind(context) : Prototype.K;
+    var trues = [], falses = [];
+    this.each(function(value, index) {
+      (iterator(value, index) ?
+        trues : falses).push(value);
+    });
+    return [trues, falses];
+  },
+
+  pluck: function(property) {
+    var results = [];
+    this.each(function(value) {
+      results.push(value[property]);
+    });
+    return results;
+  },
+
+  reject: function(iterator, context) {
+    iterator = iterator.bind(context);
+    var results = [];
+    this.each(function(value, index) {
+      if (!iterator(value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  sortBy: function(iterator, context) {
+    iterator = iterator.bind(context);
+    return this.map(function(value, index) {
+      return {value: value, criteria: iterator(value, index)};
+    }).sort(function(left, right) {
+      var a = left.criteria, b = right.criteria;
+      return a < b ? -1 : a > b ? 1 : 0;
+    }).pluck('value');
+  },
+
+  toArray: function() {
+    return this.map();
+  },
+
+  zip: function() {
+    var iterator = Prototype.K, args = $A(arguments);
+    if (Object.isFunction(args.last()))
+      iterator = args.pop();
+
+    var collections = [this].concat(args).map($A);
+    return this.map(function(value, index) {
+      return iterator(collections.pluck(index));
+    });
+  },
+
+  size: function() {
+    return this.toArray().length;
+  },
+
+  inspect: function() {
+    return '#<Enumerable:' + this.toArray().inspect() + '>';
+  }
+};
+
+Object.extend(Enumerable, {
+  map:     Enumerable.collect,
+  find:    Enumerable.detect,
+  select:  Enumerable.findAll,
+  filter:  Enumerable.findAll,
+  member:  Enumerable.include,
+  entries: Enumerable.toArray,
+  every:   Enumerable.all,
+  some:    Enumerable.any
+});
+function $A(iterable) {
+  if (!iterable) return [];
+  if (iterable.toArray) return iterable.toArray();
+  var length = iterable.length, results = new Array(length);
+  while (length--) results[length] = iterable[length];
+  return results;
+}
+
+if (Prototype.Browser.WebKit) {
+  function $A(iterable) {
+    if (!iterable) return [];
+    if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+        iterable.toArray) return iterable.toArray();
+    var length = iterable.length, results = new Array(length);
+    while (length--) results[length] = iterable[length];
+    return results;
+  }
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+  _each: function(iterator) {
+    for (var i = 0, length = this.length; i < length; i++)
+      iterator(this[i]);
+  },
+
+  clear: function() {
+    this.length = 0;
+    return this;
+  },
+
+  first: function() {
+    return this[0];
+  },
+
+  last: function() {
+    return this[this.length - 1];
+  },
+
+  compact: function() {
+    return this.select(function(value) {
+      return value != null;
+    });
+  },
+
+  flatten: function() {
+    return this.inject([], function(array, value) {
+      return array.concat(Object.isArray(value) ?
+        value.flatten() : [value]);
+    });
+  },
+
+  without: function() {
+    var values = $A(arguments);
+    return this.select(function(value) {
+      return !values.include(value);
+    });
+  },
+
+  reverse: function(inline) {
+    return (inline !== false ? this : this.toArray())._reverse();
+  },
+
+  reduce: function() {
+    return this.length > 1 ? this : this[0];
+  },
+
+  uniq: function(sorted) {
+    return this.inject([], function(array, value, index) {
+      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+        array.push(value);
+      return array;
+    });
+  },
+
+  intersect: function(array) {
+    return this.uniq().findAll(function(item) {
+      return array.detect(function(value) { return item === value });
+    });
+  },
+
+  clone: function() {
+    return [].concat(this);
+  },
+
+  size: function() {
+    return this.length;
+  },
+
+  inspect: function() {
+    return '[' + this.map(Object.inspect).join(', ') + ']';
+  },
+
+  toJSON: function() {
+    var results = [];
+    this.each(function(object) {
+      var value = Object.toJSON(object);
+      if (value !== undefined) results.push(value);
+    });
+    return '[' + results.join(', ') + ']';
+  }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+  Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+  i || (i = 0);
+  var length = this.length;
+  if (i < 0) i = length + i;
+  for (; i < length; i++)
+    if (this[i] === item) return i;
+  return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+  i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+  var n = this.slice(0, i).reverse().indexOf(item);
+  return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+  if (!Object.isString(string)) return [];
+  string = string.strip();
+  return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+  Array.prototype.concat = function() {
+    var array = [];
+    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+    for (var i = 0, length = arguments.length; i < length; i++) {
+      if (Object.isArray(arguments[i])) {
+        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+          array.push(arguments[i][j]);
+      } else {
+        array.push(arguments[i]);
+      }
+    }
+    return array;
+  };
+}
+Object.extend(Number.prototype, {
+  toColorPart: function() {
+    return this.toPaddedString(2, 16);
+  },
+
+  succ: function() {
+    return this + 1;
+  },
+
+  times: function(iterator) {
+    $R(0, this, true).each(iterator);
+    return this;
+  },
+
+  toPaddedString: function(length, radix) {
+    var string = this.toString(radix || 10);
+    return '0'.times(length - string.length) + string;
+  },
+
+  toJSON: function() {
+    return isFinite(this) ? this.toString() : 'null';
+  }
+});
+
+$w('abs round ceil floor').each(function(method){
+  Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+  return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+  if (function() {
+    var i = 0, Test = function(value) { this.key = value };
+    Test.prototype.key = 'foo';
+    for (var property in new Test('bar')) i++;
+    return i > 1;
+  }()) {
+    function each(iterator) {
+      var cache = [];
+      for (var key in this._object) {
+        var value = this._object[key];
+        if (cache.include(key)) continue;
+        cache.push(key);
+        var pair = [key, value];
+        pair.key = key;
+        pair.value = value;
+        iterator(pair);
+      }
+    }
+  } else {
+    function each(iterator) {
+      for (var key in this._object) {
+        var value = this._object[key], pair = [key, value];
+        pair.key = key;
+        pair.value = value;
+        iterator(pair);
+      }
+    }
+  }
+
+  function toQueryPair(key, value) {
+    if (Object.isUndefined(value)) return key;
+    return key + '=' + encodeURIComponent(String.interpret(value));
+  }
+
+  return {
+    initialize: function(object) {
+      this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+    },
+
+    _each: each,
+
+    set: function(key, value) {
+      return this._object[key] = value;
+    },
+
+    get: function(key) {
+      return this._object[key];
+    },
+
+    unset: function(key) {
+      var value = this._object[key];
+      delete this._object[key];
+      return value;
+    },
+
+    toObject: function() {
+      return Object.clone(this._object);
+    },
+
+    keys: function() {
+      return this.pluck('key');
+    },
+
+    values: function() {
+      return this.pluck('value');
+    },
+
+    index: function(value) {
+      var match = this.detect(function(pair) {
+        return pair.value === value;
+      });
+      return match && match.key;
+    },
+
+    merge: function(object) {
+      return this.clone().update(object);
+    },
+
+    update: function(object) {
+      return new Hash(object).inject(this, function(result, pair) {
+        result.set(pair.key, pair.value);
+        return result;
+      });
+    },
+
+    toQueryString: function() {
+      return this.map(function(pair) {
+        var key = encodeURIComponent(pair.key), values = pair.value;
+
+        if (values && typeof values == 'object') {
+          if (Object.isArray(values))
+            return values.map(toQueryPair.curry(key)).join('&');
+        }
+        return toQueryPair(key, values);
+      }).join('&');
+    },
+
+    inspect: function() {
+      return '#<Hash:{' + this.map(function(pair) {
+        return pair.map(Object.inspect).join(': ');
+      }).join(', ') + '}>';
+    },
+
+    toJSON: function() {
+      return Object.toJSON(this.toObject());
+    },
+
+    clone: function() {
+      return new Hash(this);
+    }
+  }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+  initialize: function(start, end, exclusive) {
+    this.start = start;
+    this.end = end;
+    this.exclusive = exclusive;
+  },
+
+  _each: function(iterator) {
+    var value = this.start;
+    while (this.include(value)) {
+      iterator(value);
+      value = value.succ();
+    }
+  },
+
+  include: function(value) {
+    if (value < this.start)
+      return false;
+    if (this.exclusive)
+      return value < this.end;
+    return value <= this.end;
+  }
+});
+
+var $R = function(start, end, exclusive) {
+  return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+  getTransport: function() {
+    return Try.these(
+      function() {return new XMLHttpRequest()},
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+    ) || false;
+  },
+
+  activeRequestCount: 0
+};
+
+Ajax.Responders = {
+  responders: [],
+
+  _each: function(iterator) {
+    this.responders._each(iterator);
+  },
+
+  register: function(responder) {
+    if (!this.include(responder))
+      this.responders.push(responder);
+  },
+
+  unregister: function(responder) {
+    this.responders = this.responders.without(responder);
+  },
+
+  dispatch: function(callback, request, transport, json) {
+    this.each(function(responder) {
+      if (Object.isFunction(responder[callback])) {
+        try {
+          responder[callback].apply(responder, [request, transport, json]);
+        } catch (e) { }
+      }
+    });
+  }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+  onCreate:   function() { Ajax.activeRequestCount++ },
+  onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+  initialize: function(options) {
+    this.options = {
+      method:       'post',
+      asynchronous: true,
+      contentType:  'application/x-www-form-urlencoded',
+      encoding:     'UTF-8',
+      parameters:   '',
+      evalJSON:     true,
+      evalJS:       true
+    };
+    Object.extend(this.options, options || { });
+
+    this.options.method = this.options.method.toLowerCase();
+    if (Object.isString(this.options.parameters))
+      this.options.parameters = this.options.parameters.toQueryParams();
+  }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+  _complete: false,
+
+  initialize: function($super, url, options) {
+    $super(options);
+    this.transport = Ajax.getTransport();
+    this.request(url);
+  },
+
+  request: function(url) {
+    this.url = url;
+    this.method = this.options.method;
+    var params = Object.clone(this.options.parameters);
+
+    if (!['get', 'post'].include(this.method)) {
+      // simulate other verbs over post
+      params['_method'] = this.method;
+      this.method = 'post';
+    }
+
+    this.parameters = params;
+
+    if (params = Object.toQueryString(params)) {
+      // when GET, append parameters to URL
+      if (this.method == 'get')
+        this.url += (this.url.include('?') ? '&' : '?') + params;
+      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+        params += '&_=';
+    }
+
+    try {
+      var response = new Ajax.Response(this);
+      if (this.options.onCreate) this.options.onCreate(response);
+      Ajax.Responders.dispatch('onCreate', this, response);
+
+      this.transport.open(this.method.toUpperCase(), this.url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+      this.transport.onreadystatechange = this.onStateChange.bind(this);
+      this.setRequestHeaders();
+
+      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+      this.transport.send(this.body);
+
+      /* Force Firefox to handle ready state 4 for synchronous requests */
+      if (!this.options.asynchronous && this.transport.overrideMimeType)
+        this.onStateChange();
+
+    }
+    catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  onStateChange: function() {
+    var readyState = this.transport.readyState;
+    if (readyState > 1 && !((readyState == 4) && this._complete))
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  setRequestHeaders: function() {
+    var headers = {
+      'X-Requested-With': 'XMLHttpRequest',
+      'X-Prototype-Version': Prototype.Version,
+      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+    };
+
+    if (this.method == 'post') {
+      headers['Content-type'] = this.options.contentType +
+        (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+      /* Force "Connection: close" for older Mozilla browsers to work
+       * around a bug where XMLHttpRequest sends an incorrect
+       * Content-length header. See Mozilla Bugzilla #246651.
+       */
+      if (this.transport.overrideMimeType &&
+          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+            headers['Connection'] = 'close';
+    }
+
+    // user-defined headers
+    if (typeof this.options.requestHeaders == 'object') {
+      var extras = this.options.requestHeaders;
+
+      if (Object.isFunction(extras.push))
+        for (var i = 0, length = extras.length; i < length; i += 2)
+          headers[extras[i]] = extras[i+1];
+      else
+        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+    }
+
+    for (var name in headers)
+      this.transport.setRequestHeader(name, headers[name]);
+  },
+
+  success: function() {
+    var status = this.getStatus();
+    return !status || (status >= 200 && status < 300);
+  },
+
+  getStatus: function() {
+    try {
+      return this.transport.status || 0;
+    } catch (e) { return 0 }
+  },
+
+  respondToReadyState: function(readyState) {
+    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+    if (state == 'Complete') {
+      try {
+        this._complete = true;
+        (this.options['on' + response.status]
+         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+         || Prototype.emptyFunction)(response, response.headerJSON);
+      } catch (e) {
+        this.dispatchException(e);
+      }
+
+      var contentType = response.getHeader('Content-type');
+      if (this.options.evalJS == 'force'
+          || (this.options.evalJS && contentType
+          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+        this.evalResponse();
+    }
+
+    try {
+      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+
+    if (state == 'Complete') {
+      // avoid memory leak in MSIE: clean up
+      this.transport.onreadystatechange = Prototype.emptyFunction;
+    }
+  },
+
+  getHeader: function(name) {
+    try {
+      return this.transport.getResponseHeader(name);
+    } catch (e) { return null }
+  },
+
+  evalResponse: function() {
+    try {
+      return eval((this.transport.responseText || '').unfilterJSON());
+    } catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  dispatchException: function(exception) {
+    (this.options.onException || Prototype.emptyFunction)(this, exception);
+    Ajax.Responders.dispatch('onException', this, exception);
+  }
+});
+
+Ajax.Request.Events =
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+  initialize: function(request){
+    this.request = request;
+    var transport  = this.transport  = request.transport,
+        readyState = this.readyState = transport.readyState;
+
+    if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+      this.status       = this.getStatus();
+      this.statusText   = this.getStatusText();
+      this.responseText = String.interpret(transport.responseText);
+      this.headerJSON   = this._getHeaderJSON();
+    }
+
+    if(readyState == 4) {
+      var xml = transport.responseXML;
+      this.responseXML  = xml === undefined ? null : xml;
+      this.responseJSON = this._getResponseJSON();
+    }
+  },
+
+  status:      0,
+  statusText: '',
+
+  getStatus: Ajax.Request.prototype.getStatus,
+
+  getStatusText: function() {
+    try {
+      return this.transport.statusText || '';
+    } catch (e) { return '' }
+  },
+
+  getHeader: Ajax.Request.prototype.getHeader,
+
+  getAllHeaders: function() {
+    try {
+      return this.getAllResponseHeaders();
+    } catch (e) { return null }
+  },
+
+  getResponseHeader: function(name) {
+    return this.transport.getResponseHeader(name);
+  },
+
+  getAllResponseHeaders: function() {
+    return this.transport.getAllResponseHeaders();
+  },
+
+  _getHeaderJSON: function() {
+    var json = this.getHeader('X-JSON');
+    if (!json) return null;
+    json = decodeURIComponent(escape(json));
+    try {
+      return json.evalJSON(this.request.options.sanitizeJSON);
+    } catch (e) {
+      this.request.dispatchException(e);
+    }
+  },
+
+  _getResponseJSON: function() {
+    var options = this.request.options;
+    if (!options.evalJSON || (options.evalJSON != 'force' &&
+      !(this.getHeader('Content-type') || '').include('application/json')))
+        return null;
+    try {
+      return this.transport.responseText.evalJSON(options.sanitizeJSON);
+    } catch (e) {
+      this.request.dispatchException(e);
+    }
+  }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+  initialize: function($super, container, url, options) {
+    this.container = {
+      success: (container.success || container),
+      failure: (container.failure || (container.success ? null : container))
+    };
+
+    options = options || { };
+    var onComplete = options.onComplete;
+    options.onComplete = (function(response, param) {
+      this.updateContent(response.responseText);
+      if (Object.isFunction(onComplete)) onComplete(response, param);
+    }).bind(this);
+
+    $super(url, options);
+  },
+
+  updateContent: function(responseText) {
+    var receiver = this.container[this.success() ? 'success' : 'failure'],
+        options = this.options;
+
+    if (!options.evalScripts) responseText = responseText.stripScripts();
+
+    if (receiver = $(receiver)) {
+      if (options.insertion) {
+        if (Object.isString(options.insertion)) {
+          var insertion = { }; insertion[options.insertion] = responseText;
+          receiver.insert(insertion);
+        }
+        else options.insertion(receiver, responseText);
+      }
+      else receiver.update(responseText);
+    }
+
+    if (this.success()) {
+      if (this.onComplete) this.onComplete.bind(this).defer();
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+  initialize: function($super, container, url, options) {
+    $super(options);
+    this.onComplete = this.options.onComplete;
+
+    this.frequency = (this.options.frequency || 2);
+    this.decay = (this.options.decay || 1);
+
+    this.updater = { };
+    this.container = container;
+    this.url = url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete = this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.options.onComplete = undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(response) {
+    if (this.options.decay) {
+      this.decay = (response.responseText == this.lastText ?
+        this.decay * this.options.decay : 1);
+
+      this.lastText = response.responseText;
+    }
+    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+  },
+
+  onTimerEvent: function() {
+    this.updater = new Ajax.Updater(this.container, this.url, this.options);
+  }
+});
+function $(element) {
+  if (arguments.length > 1) {
+    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+      elements.push($(arguments[i]));
+    return elements;
+  }
+  if (Object.isString(element))
+    element = document.getElementById(element);
+  return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+  document._getElementsByXPath = function(expression, parentElement) {
+    var results = [];
+    var query = document.evaluate(expression, $(parentElement) || document,
+      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+    for (var i = 0, length = query.snapshotLength; i < length; i++)
+      results.push(Element.extend(query.snapshotItem(i)));
+    return results;
+  };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+  // DOM level 2 ECMAScript Language Binding
+  Object.extend(Node, {
+    ELEMENT_NODE: 1,
+    ATTRIBUTE_NODE: 2,
+    TEXT_NODE: 3,
+    CDATA_SECTION_NODE: 4,
+    ENTITY_REFERENCE_NODE: 5,
+    ENTITY_NODE: 6,
+    PROCESSING_INSTRUCTION_NODE: 7,
+    COMMENT_NODE: 8,
+    DOCUMENT_NODE: 9,
+    DOCUMENT_TYPE_NODE: 10,
+    DOCUMENT_FRAGMENT_NODE: 11,
+    NOTATION_NODE: 12
+  });
+}
+
+(function() {
+  var element = this.Element;
+  this.Element = function(tagName, attributes) {
+    attributes = attributes || { };
+    tagName = tagName.toLowerCase();
+    var cache = Element.cache;
+    if (Prototype.Browser.IE && attributes.name) {
+      tagName = '<' + tagName + ' name="' + attributes.name + '">';
+      delete attributes.name;
+      return Element.writeAttribute(document.createElement(tagName), attributes);
+    }
+    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+  };
+  Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+  visible: function(element) {
+    return $(element).style.display != 'none';
+  },
+
+  toggle: function(element) {
+    element = $(element);
+    Element[Element.visible(element) ? 'hide' : 'show'](element);
+    return element;
+  },
+
+  hide: function(element) {
+    $(element).style.display = 'none';
+    return element;
+  },
+
+  show: function(element) {
+    $(element).style.display = '';
+    return element;
+  },
+
+  remove: function(element) {
+    element = $(element);
+    element.parentNode.removeChild(element);
+    return element;
+  },
+
+  update: function(element, content) {
+    element = $(element);
+    if (content && content.toElement) content = content.toElement();
+    if (Object.isElement(content)) return element.update().insert(content);
+    content = Object.toHTML(content);
+    element.innerHTML = content.stripScripts();
+    content.evalScripts.bind(content).defer();
+    return element;
+  },
+
+  replace: function(element, content) {
+    element = $(element);
+    if (content && content.toElement) content = content.toElement();
+    else if (!Object.isElement(content)) {
+      content = Object.toHTML(content);
+      var range = element.ownerDocument.createRange();
+      range.selectNode(element);
+      content.evalScripts.bind(content).defer();
+      content = range.createContextualFragment(content.stripScripts());
+    }
+    element.parentNode.replaceChild(content, element);
+    return element;
+  },
+
+  insert: function(element, insertions) {
+    element = $(element);
+
+    if (Object.isString(insertions) || Object.isNumber(insertions) ||
+        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+          insertions = {bottom:insertions};
+
+    var content, t, range;
+
+    for (position in insertions) {
+      content  = insertions[position];
+      position = position.toLowerCase();
+      t = Element._insertionTranslations[position];
+
+      if (content && content.toElement) content = content.toElement();
+      if (Object.isElement(content)) {
+        t.insert(element, content);
+        continue;
+      }
+
+      content = Object.toHTML(content);
+
+      range = element.ownerDocument.createRange();
+      t.initializeRange(element, range);
+      t.insert(element, range.createContextualFragment(content.stripScripts()));
+
+      content.evalScripts.bind(content).defer();
+    }
+
+    return element;
+  },
+
+  wrap: function(element, wrapper, attributes) {
+    element = $(element);
+    if (Object.isElement(wrapper))
+      $(wrapper).writeAttribute(attributes || { });
+    else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+    else wrapper = new Element('div', wrapper);
+    if (element.parentNode)
+      element.parentNode.replaceChild(wrapper, element);
+    wrapper.appendChild(element);
+    return wrapper;
+  },
+
+  inspect: function(element) {
+    element = $(element);
+    var result = '<' + element.tagName.toLowerCase();
+    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+      var property = pair.first(), attribute = pair.last();
+      var value = (element[property] || '').toString();
+      if (value) result += ' ' + attribute + '=' + value.inspect(true);
+    });
+    return result + '>';
+  },
+
+  recursivelyCollect: function(element, property) {
+    element = $(element);
+    var elements = [];
+    while (element = element[property])
+      if (element.nodeType == 1)
+        elements.push(Element.extend(element));
+    return elements;
+  },
+
+  ancestors: function(element) {
+    return $(element).recursivelyCollect('parentNode');
+  },
+
+  descendants: function(element) {
+    return $A($(element).getElementsByTagName('*')).each(Element.extend);
+  },
+
+  firstDescendant: function(element) {
+    element = $(element).firstChild;
+    while (element && element.nodeType != 1) element = element.nextSibling;
+    return $(element);
+  },
+
+  immediateDescendants: function(element) {
+    if (!(element = $(element).firstChild)) return [];
+    while (element && element.nodeType != 1) element = element.nextSibling;
+    if (element) return [element].concat($(element).nextSiblings());
+    return [];
+  },
+
+  previousSiblings: function(element) {
+    return $(element).recursivelyCollect('previousSibling');
+  },
+
+  nextSiblings: function(element) {
+    return $(element).recursivelyCollect('nextSibling');
+  },
+
+  siblings: function(element) {
+    element = $(element);
+    return element.previousSiblings().reverse().concat(element.nextSiblings());
+  },
+
+  match: function(element, selector) {
+    if (Object.isString(selector))
+      selector = new Selector(selector);
+    return selector.match($(element));
+  },
+
+  up: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return $(element.parentNode);
+    var ancestors = element.ancestors();
+    return expression ? Selector.findElement(ancestors, expression, index) :
+      ancestors[index || 0];
+  },
+
+  down: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return element.firstDescendant();
+    var descendants = element.descendants();
+    return expression ? Selector.findElement(descendants, expression, index) :
+      descendants[index || 0];
+  },
+
+  previous: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+    var previousSiblings = element.previousSiblings();
+    return expression ? Selector.findElement(previousSiblings, expression, index) :
+      previousSiblings[index || 0];
+  },
+
+  next: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+    var nextSiblings = element.nextSiblings();
+    return expression ? Selector.findElement(nextSiblings, expression, index) :
+      nextSiblings[index || 0];
+  },
+
+  select: function() {
+    var args = $A(arguments), element = $(args.shift());
+    return Selector.findChildElements(element, args);
+  },
+
+  adjacent: function() {
+    var args = $A(arguments), element = $(args.shift());
+    return Selector.findChildElements(element.parentNode, args).without(element);
+  },
+
+  identify: function(element) {
+    element = $(element);
+    var id = element.readAttribute('id'), self = arguments.callee;
+    if (id) return id;
+    do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+    element.writeAttribute('id', id);
+    return id;
+  },
+
+  readAttribute: function(element, name) {
+    element = $(element);
+    if (Prototype.Browser.IE) {
+      var t = Element._attributeTranslations.read;
+      if (t.values[name]) return t.values[name](element, name);
+      if (t.names[name]) name = t.names[name];
+      if (name.include(':')) {
+        return (!element.attributes || !element.attributes[name]) ? null :
+         element.attributes[name].value;
+      }
+    }
+    return element.getAttribute(name);
+  },
+
+  writeAttribute: function(element, name, value) {
+    element = $(element);
+    var attributes = { }, t = Element._attributeTranslations.write;
+
+    if (typeof name == 'object') attributes = name;
+    else attributes[name] = value === undefined ? true : value;
+
+    for (var attr in attributes) {
+      var name = t.names[attr] || attr, value = attributes[attr];
+      if (t.values[attr]) name = t.values[attr](element, value);
+      if (value === false || value === null)
+        element.removeAttribute(name);
+      else if (value === true)
+        element.setAttribute(name, name);
+      else element.setAttribute(name, value);
+    }
+    return element;
+  },
+
+  getHeight: function(element) {
+    return $(element).getDimensions().height;
+  },
+
+  getWidth: function(element) {
+    return $(element).getDimensions().width;
+  },
+
+  classNames: function(element) {
+    return new Element.ClassNames(element);
+  },
+
+  hasClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    var elementClassName = element.className;
+    return (elementClassName.length > 0 && (elementClassName == className ||
+      new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+  },
+
+  addClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    if (!element.hasClassName(className))
+      element.className += (element.className ? ' ' : '') + className;
+    return element;
+  },
+
+  removeClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    element.className = element.className.replace(
+      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+    return element;
+  },
+
+  toggleClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    return element[element.hasClassName(className) ?
+      'removeClassName' : 'addClassName'](className);
+  },
+
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    element = $(element);
+    var node = element.firstChild;
+    while (node) {
+      var nextNode = node.nextSibling;
+      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+        element.removeChild(node);
+      node = nextNode;
+    }
+    return element;
+  },
+
+  empty: function(element) {
+    return $(element).innerHTML.blank();
+  },
+
+  descendantOf: function(element, ancestor) {
+    element = $(element), ancestor = $(ancestor);
+
+    if (element.compareDocumentPosition)
+      return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+    if (element.sourceIndex && !Prototype.Browser.Opera) {
+      var e = element.sourceIndex, a = ancestor.sourceIndex,
+       nextAncestor = ancestor.nextSibling;
+      if (!nextAncestor) {
+        do { ancestor = ancestor.parentNode; }
+        while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+      }
+      if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex);
+    }
+
+    while (element = element.parentNode)
+      if (element == ancestor) return true;
+    return false;
+  },
+
+  scrollTo: function(element) {
+    element = $(element);
+    var pos = element.cumulativeOffset();
+    window.scrollTo(pos[0], pos[1]);
+    return element;
+  },
+
+  getStyle: function(element, style) {
+    element = $(element);
+    style = style == 'float' ? 'cssFloat' : style.camelize();
+    var value = element.style[style];
+    if (!value) {
+      var css = document.defaultView.getComputedStyle(element, null);
+      value = css ? css[style] : null;
+    }
+    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+    return value == 'auto' ? null : value;
+  },
+
+  getOpacity: function(element) {
+    return $(element).getStyle('opacity');
+  },
+
+  setStyle: function(element, styles) {
+    element = $(element);
+    var elementStyle = element.style, match;
+    if (Object.isString(styles)) {
+      element.style.cssText += ';' + styles;
+      return styles.include('opacity') ?
+        element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+    }
+    for (var property in styles)
+      if (property == 'opacity') element.setOpacity(styles[property]);
+      else
+        elementStyle[(property == 'float' || property == 'cssFloat') ?
+          (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
+            property] = styles[property];
+
+    return element;
+  },
+
+  setOpacity: function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1 || value === '') ? '' :
+      (value < 0.00001) ? 0 : value;
+    return element;
+  },
+
+  getDimensions: function(element) {
+    element = $(element);
+    var display = $(element).getStyle('display');
+    if (display != 'none' && display != null) // Safari bug
+      return {width: element.offsetWidth, height: element.offsetHeight};
+
+    // All *Width and *Height properties give 0 on elements with display none,
+    // so enable the element temporarily
+    var els = element.style;
+    var originalVisibility = els.visibility;
+    var originalPosition = els.position;
+    var originalDisplay = els.display;
+    els.visibility = 'hidden';
+    els.position = 'absolute';
+    els.display = 'block';
+    var originalWidth = element.clientWidth;
+    var originalHeight = element.clientHeight;
+    els.display = originalDisplay;
+    els.position = originalPosition;
+    els.visibility = originalVisibility;
+    return {width: originalWidth, height: originalHeight};
+  },
+
+  makePositioned: function(element) {
+    element = $(element);
+    var pos = Element.getStyle(element, 'position');
+    if (pos == 'static' || !pos) {
+      element._madePositioned = true;
+      element.style.position = 'relative';
+      // Opera returns the offset relative to the positioning context, when an
+      // element is position relative but top and left have not been defined
+      if (window.opera) {
+        element.style.top = 0;
+        element.style.left = 0;
+      }
+    }
+    return element;
+  },
+
+  undoPositioned: function(element) {
+    element = $(element);
+    if (element._madePositioned) {
+      element._madePositioned = undefined;
+      element.style.position =
+        element.style.top =
+        element.style.left =
+        element.style.bottom =
+        element.style.right = '';
+    }
+    return element;
+  },
+
+  makeClipping: function(element) {
+    element = $(element);
+    if (element._overflow) return element;
+    element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+    if (element._overflow !== 'hidden')
+      element.style.overflow = 'hidden';
+    return element;
+  },
+
+  undoClipping: function(element) {
+    element = $(element);
+    if (!element._overflow) return element;
+    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+    element._overflow = null;
+    return element;
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+    } while (element);
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  positionedOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+      if (element) {
+        if (element.tagName == 'BODY') break;
+        var p = Element.getStyle(element, 'position');
+        if (p == 'relative' || p == 'absolute') break;
+      }
+    } while (element);
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  absolutize: function(element) {
+    element = $(element);
+    if (element.getStyle('position') == 'absolute') return;
+    // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+    var offsets = element.positionedOffset();
+    var top     = offsets[1];
+    var left    = offsets[0];
+    var width   = element.clientWidth;
+    var height  = element.clientHeight;
+
+    element._originalLeft   = left - parseFloat(element.style.left  || 0);
+    element._originalTop    = top  - parseFloat(element.style.top || 0);
+    element._originalWidth  = element.style.width;
+    element._originalHeight = element.style.height;
+
+    element.style.position = 'absolute';
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.width  = width + 'px';
+    element.style.height = height + 'px';
+    return element;
+  },
+
+  relativize: function(element) {
+    element = $(element);
+    if (element.getStyle('position') == 'relative') return;
+    // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+    element.style.position = 'relative';
+    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
+    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.height = element._originalHeight;
+    element.style.width  = element._originalWidth;
+    return element;
+  },
+
+  cumulativeScrollOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.scrollTop  || 0;
+      valueL += element.scrollLeft || 0;
+      element = element.parentNode;
+    } while (element);
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  getOffsetParent: function(element) {
+    if (element.offsetParent) return $(element.offsetParent);
+    if (element == document.body) return $(element);
+
+    while ((element = element.parentNode) && element != document.body)
+      if (Element.getStyle(element, 'position') != 'static')
+        return $(element);
+
+    return $(document.body);
+  },
+
+  viewportOffset: function(forElement) {
+    var valueT = 0, valueL = 0;
+
+    var element = forElement;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+
+      // Safari fix
+      if (element.offsetParent == document.body &&
+        Element.getStyle(element, 'position') == 'absolute') break;
+
+    } while (element = element.offsetParent);
+
+    element = forElement;
+    do {
+      if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+        valueT -= element.scrollTop  || 0;
+        valueL -= element.scrollLeft || 0;
+      }
+    } while (element = element.parentNode);
+
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  clonePosition: function(element, source) {
+    var options = Object.extend({
+      setLeft:    true,
+      setTop:     true,
+      setWidth:   true,
+      setHeight:  true,
+      offsetTop:  0,
+      offsetLeft: 0
+    }, arguments[2] || { });
+
+    // find page position of source
+    source = $(source);
+    var p = source.viewportOffset();
+
+    // find coordinate system to use
+    element = $(element);
+    var delta = [0, 0];
+    var parent = null;
+    // delta [0,0] will do fine with position: fixed elements,
+    // position:absolute needs offsetParent deltas
+    if (Element.getStyle(element, 'position') == 'absolute') {
+      parent = element.getOffsetParent();
+      delta = parent.viewportOffset();
+    }
+
+    // correct by body offsets (fixes Safari)
+    if (parent == document.body) {
+      delta[0] -= document.body.offsetLeft;
+      delta[1] -= document.body.offsetTop;
+    }
+
+    // set position
+    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
+    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
+    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';
+    if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+    return element;
+  }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+  getElementsBySelector: Element.Methods.select,
+  childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+  write: {
+    names: {
+      className: 'class',
+      htmlFor:   'for'
+    },
+    values: { }
+  }
+};
+
+
+if (!document.createRange || Prototype.Browser.Opera) {
+  Element.Methods.insert = function(element, insertions) {
+    element = $(element);
+
+    if (Object.isString(insertions) || Object.isNumber(insertions) ||
+        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+          insertions = { bottom: insertions };
+
+    var t = Element._insertionTranslations, content, position, pos, tagName;
+
+    for (position in insertions) {
+      content  = insertions[position];
+      position = position.toLowerCase();
+      pos      = t[position];
+
+      if (content && content.toElement) content = content.toElement();
+      if (Object.isElement(content)) {
+        pos.insert(element, content);
+        continue;
+      }
+
+      content = Object.toHTML(content);
+      tagName = ((position == 'before' || position == 'after')
+        ? element.parentNode : element).tagName.toUpperCase();
+
+      if (t.tags[tagName]) {
+        var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+        if (position == 'top' || position == 'after') fragments.reverse();
+        fragments.each(pos.insert.curry(element));
+      }
+      else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());
+
+      content.evalScripts.bind(content).defer();
+    }
+
+    return element;
+  };
+}
+
+if (Prototype.Browser.Opera) {
+  Element.Methods._getStyle = Element.Methods.getStyle;
+  Element.Methods.getStyle = function(element, style) {
+    switch(style) {
+      case 'left':
+      case 'top':
+      case 'right':
+      case 'bottom':
+        if (Element._getStyle(element, 'position') == 'static') return null;
+      default: return Element._getStyle(element, style);
+    }
+  };
+  Element.Methods._readAttribute = Element.Methods.readAttribute;
+  Element.Methods.readAttribute = function(element, attribute) {
+    if (attribute == 'title') return element.title;
+    return Element._readAttribute(element, attribute);
+  };
+}
+
+else if (Prototype.Browser.IE) {
+  $w('positionedOffset getOffsetParent viewportOffset').each(function(method) {
+    Element.Methods[method] = Element.Methods[method].wrap(
+      function(proceed, element) {
+        element = $(element);
+        var position = element.getStyle('position');
+        if (position != 'static') return proceed(element);
+        element.setStyle({ position: 'relative' });
+        var value = proceed(element);
+        element.setStyle({ position: position });
+        return value;
+      }
+    );
+  });
+
+  Element.Methods.getStyle = function(element, style) {
+    element = $(element);
+    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+    var value = element.style[style];
+    if (!value && element.currentStyle) value = element.currentStyle[style];
+
+    if (style == 'opacity') {
+      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+        if (value[1]) return parseFloat(value[1]) / 100;
+      return 1.0;
+    }
+
+    if (value == 'auto') {
+      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+        return element['offset' + style.capitalize()] + 'px';
+      return null;
+    }
+    return value;
+  };
+
+  Element.Methods.setOpacity = function(element, value) {
+    function stripAlpha(filter){
+      return filter.replace(/alpha\([^\)]*\)/gi,'');
+    }
+    element = $(element);
+    var currentStyle = element.currentStyle;
+    if ((currentStyle && !currentStyle.hasLayout) ||
+      (!currentStyle && element.style.zoom == 'normal'))
+        element.style.zoom = 1;
+
+    var filter = element.getStyle('filter'), style = element.style;
+    if (value == 1 || value === '') {
+      (filter = stripAlpha(filter)) ?
+        style.filter = filter : style.removeAttribute('filter');
+      return element;
+    } else if (value < 0.00001) value = 0;
+    style.filter = stripAlpha(filter) +
+      'alpha(opacity=' + (value * 100) + ')';
+    return element;
+  };
+
+  Element._attributeTranslations = {
+    read: {
+      names: {
+        'class': 'className',
+        'for':   'htmlFor'
+      },
+      values: {
+        _getAttr: function(element, attribute) {
+          return element.getAttribute(attribute, 2);
+        },
+        _getAttrNode: function(element, attribute) {
+          var node = element.getAttributeNode(attribute);
+          return node ? node.value : "";
+        },
+        _getEv: function(element, attribute) {
+          var attribute = element.getAttribute(attribute);
+          return attribute ? attribute.toString().slice(23, -2) : null;
+        },
+        _flag: function(element, attribute) {
+          return $(element).hasAttribute(attribute) ? attribute : null;
+        },
+        style: function(element) {
+          return element.style.cssText.toLowerCase();
+        },
+        title: function(element) {
+          return element.title;
+        }
+      }
+    }
+  };
+
+  Element._attributeTranslations.write = {
+    names: Object.clone(Element._attributeTranslations.read.names),
+    values: {
+      checked: function(element, value) {
+        element.checked = !!value;
+      },
+
+      style: function(element, value) {
+        element.style.cssText = value ? value : '';
+      }
+    }
+  };
+
+  Element._attributeTranslations.has = {};
+
+  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+      'encType maxLength readOnly longDesc').each(function(attr) {
+    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+    Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+  });
+
+  (function(v) {
+    Object.extend(v, {
+      href:        v._getAttr,
+      src:         v._getAttr,
+      type:        v._getAttr,
+      action:      v._getAttrNode,
+      disabled:    v._flag,
+      checked:     v._flag,
+      readonly:    v._flag,
+      multiple:    v._flag,
+      onload:      v._getEv,
+      onunload:    v._getEv,
+      onclick:     v._getEv,
+      ondblclick:  v._getEv,
+      onmousedown: v._getEv,
+      onmouseup:   v._getEv,
+      onmouseover: v._getEv,
+      onmousemove: v._getEv,
+      onmouseout:  v._getEv,
+      onfocus:     v._getEv,
+      onblur:      v._getEv,
+      onkeypress:  v._getEv,
+      onkeydown:   v._getEv,
+      onkeyup:     v._getEv,
+      onsubmit:    v._getEv,
+      onreset:     v._getEv,
+      onselect:    v._getEv,
+      onchange:    v._getEv
+    });
+  })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+  Element.Methods.setOpacity = function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1) ? 0.999999 :
+      (value === '') ? '' : (value < 0.00001) ? 0 : value;
+    return element;
+  };
+}
+
+else if (Prototype.Browser.WebKit) {
+  Element.Methods.setOpacity = function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1 || value === '') ? '' :
+      (value < 0.00001) ? 0 : value;
+
+    if (value == 1)
+      if(element.tagName == 'IMG' && element.width) {
+        element.width++; element.width--;
+      } else try {
+        var n = document.createTextNode(' ');
+        element.appendChild(n);
+        element.removeChild(n);
+      } catch (e) { }
+
+    return element;
+  };
+
+  // Safari returns margins on body which is incorrect if the child is absolutely
+  // positioned.  For performance reasons, redefine Position.cumulativeOffset for
+  // KHTML/WebKit only.
+  Element.Methods.cumulativeOffset = function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      if (element.offsetParent == document.body)
+        if (Element.getStyle(element, 'position') == 'absolute') break;
+
+      element = element.offsetParent;
+    } while (element);
+
+    return Element._returnOffset(valueL, valueT);
+  };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+  // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+  Element.Methods.update = function(element, content) {
+    element = $(element);
+
+    if (content && content.toElement) content = content.toElement();
+    if (Object.isElement(content)) return element.update().insert(content);
+
+    content = Object.toHTML(content);
+    var tagName = element.tagName.toUpperCase();
+
+    if (tagName in Element._insertionTranslations.tags) {
+      $A(element.childNodes).each(function(node) { element.removeChild(node) });
+      Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+        .each(function(node) { element.appendChild(node) });
+    }
+    else element.innerHTML = content.stripScripts();
+
+    content.evalScripts.bind(content).defer();
+    return element;
+  };
+}
+
+if (document.createElement('div').outerHTML) {
+  Element.Methods.replace = function(element, content) {
+    element = $(element);
+
+    if (content && content.toElement) content = content.toElement();
+    if (Object.isElement(content)) {
+      element.parentNode.replaceChild(content, element);
+      return element;
+    }
+
+    content = Object.toHTML(content);
+    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+    if (Element._insertionTranslations.tags[tagName]) {
+      var nextSibling = element.next();
+      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+      parent.removeChild(element);
+      if (nextSibling)
+        fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+      else
+        fragments.each(function(node) { parent.appendChild(node) });
+    }
+    else element.outerHTML = content.stripScripts();
+
+    content.evalScripts.bind(content).defer();
+    return element;
+  };
+}
+
+Element._returnOffset = function(l, t) {
+  var result = [l, t];
+  result.left = l;
+  result.top = t;
+  return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+  div.innerHTML = t[0] + html + t[1];
+  t[2].times(function() { div = div.firstChild });
+  return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+  before: {
+    adjacency: 'beforeBegin',
+    insert: function(element, node) {
+      element.parentNode.insertBefore(node, element);
+    },
+    initializeRange: function(element, range) {
+      range.setStartBefore(element);
+    }
+  },
+  top: {
+    adjacency: 'afterBegin',
+    insert: function(element, node) {
+      element.insertBefore(node, element.firstChild);
+    },
+    initializeRange: function(element, range) {
+      range.selectNodeContents(element);
+      range.collapse(true);
+    }
+  },
+  bottom: {
+    adjacency: 'beforeEnd',
+    insert: function(element, node) {
+      element.appendChild(node);
+    }
+  },
+  after: {
+    adjacency: 'afterEnd',
+    insert: function(element, node) {
+      element.parentNode.insertBefore(node, element.nextSibling);
+    },
+    initializeRange: function(element, range) {
+      range.setStartAfter(element);
+    }
+  },
+  tags: {
+    TABLE:  ['<table>',                '</table>',                   1],
+    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],
+    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],
+    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+    SELECT: ['<select>',               '</select>',                  1]
+  }
+};
+
+(function() {
+  this.bottom.initializeRange = this.top.initializeRange;
+  Object.extend(this.tags, {
+    THEAD: this.tags.TBODY,
+    TFOOT: this.tags.TBODY,
+    TH:    this.tags.TD
+  });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+  hasAttribute: function(element, attribute) {
+    attribute = Element._attributeTranslations.has[attribute] || attribute;
+    var node = $(element).getAttributeNode(attribute);
+    return node && node.specified;
+  }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+    document.createElement('div').__proto__) {
+  window.HTMLElement = { };
+  window.HTMLElement.prototype = document.createElement('div').__proto__;
+  Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+  if (Prototype.BrowserFeatures.SpecificElementExtensions)
+    return Prototype.K;
+
+  var Methods = { }, ByTag = Element.Methods.ByTag;
+
+  var extend = Object.extend(function(element) {
+    if (!element || element._extendedByPrototype ||
+        element.nodeType != 1 || element == window) return element;
+
+    var methods = Object.clone(Methods),
+      tagName = element.tagName, property, value;
+
+    // extend methods for specific tags
+    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+    for (property in methods) {
+      value = methods[property];
+      if (Object.isFunction(value) && !(property in element))
+        element[property] = value.methodize();
+    }
+
+    element._extendedByPrototype = Prototype.emptyFunction;
+    return element;
+
+  }, {
+    refresh: function() {
+      // extend methods for all tags (Safari doesn't need this)
+      if (!Prototype.BrowserFeatures.ElementExtensions) {
+        Object.extend(Methods, Element.Methods);
+        Object.extend(Methods, Element.Methods.Simulated);
+      }
+    }
+  });
+
+  extend.refresh();
+  return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+  if (element.hasAttribute) return element.hasAttribute(attribute);
+  return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+  if (!methods) {
+    Object.extend(Form, Form.Methods);
+    Object.extend(Form.Element, Form.Element.Methods);
+    Object.extend(Element.Methods.ByTag, {
+      "FORM":     Object.clone(Form.Methods),
+      "INPUT":    Object.clone(Form.Element.Methods),
+      "SELECT":   Object.clone(Form.Element.Methods),
+      "TEXTAREA": Object.clone(Form.Element.Methods)
+    });
+  }
+
+  if (arguments.length == 2) {
+    var tagName = methods;
+    methods = arguments[1];
+  }
+
+  if (!tagName) Object.extend(Element.Methods, methods || { });
+  else {
+    if (Object.isArray(tagName)) tagName.each(extend);
+    else extend(tagName);
+  }
+
+  function extend(tagName) {
+    tagName = tagName.toUpperCase();
+    if (!Element.Methods.ByTag[tagName])
+      Element.Methods.ByTag[tagName] = { };
+    Object.extend(Element.Methods.ByTag[tagName], methods);
+  }
+
+  function copy(methods, destination, onlyIfAbsent) {
+    onlyIfAbsent = onlyIfAbsent || false;
+    for (var property in methods) {
+      var value = methods[property];
+      if (!Object.isFunction(value)) continue;
+      if (!onlyIfAbsent || !(property in destination))
+        destination[property] = value.methodize();
+    }
+  }
+
+  function findDOMClass(tagName) {
+    var klass;
+    var trans = {
+      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+      "FrameSet", "IFRAME": "IFrame"
+    };
+    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+    if (window[klass]) return window[klass];
+    klass = 'HTML' + tagName + 'Element';
+    if (window[klass]) return window[klass];
+    klass = 'HTML' + tagName.capitalize() + 'Element';
+    if (window[klass]) return window[klass];
+
+    window[klass] = { };
+    window[klass].prototype = document.createElement(tagName).__proto__;
+    return window[klass];
+  }
+
+  if (F.ElementExtensions) {
+    copy(Element.Methods, HTMLElement.prototype);
+    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+  }
+
+  if (F.SpecificElementExtensions) {
+    for (var tag in Element.Methods.ByTag) {
+      var klass = findDOMClass(tag);
+      if (Object.isUndefined(klass)) continue;
+      copy(T[tag], klass.prototype);
+    }
+  }
+
+  Object.extend(Element, Element.Methods);
+  delete Element.ByTag;
+
+  if (Element.extend.refresh) Element.extend.refresh();
+  Element.cache = { };
+};
+
+document.viewport = {
+  getDimensions: function() {
+    var dimensions = { };
+    $w('width height').each(function(d) {
+      var D = d.capitalize();
+      dimensions[d] = self['inner' + D] ||
+       (document.documentElement['client' + D] || document.body['client' + D]);
+    });
+    return dimensions;
+  },
+
+  getWidth: function() {
+    return this.getDimensions().width;
+  },
+
+  getHeight: function() {
+    return this.getDimensions().height;
+  },
+
+  getScrollOffsets: function() {
+    return Element._returnOffset(
+      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+      window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+  }
+};
+/* Portions of the Selector class are derived from Jack Slocumâs DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license.  Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+  initialize: function(expression) {
+    this.expression = expression.strip();
+    this.compileMatcher();
+  },
+
+  compileMatcher: function() {
+    // Selectors with namespaced attributes can't use the XPath version
+    if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression))
+      return this.compileXPathMatcher();
+
+    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+        c = Selector.criteria, le, p, m;
+
+    if (Selector._cache[e]) {
+      this.matcher = Selector._cache[e];
+      return;
+    }
+
+    this.matcher = ["this.matcher = function(root) {",
+                    "var r = root, h = Selector.handlers, c = false, n;"];
+
+    while (e && le != e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        p = ps[i];
+        if (m = e.match(p)) {
+          this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+    	      new Template(c[i]).evaluate(m));
+          e = e.replace(m[0], '');
+          break;
+        }
+      }
+    }
+
+    this.matcher.push("return h.unique(n);\n}");
+    eval(this.matcher.join('\n'));
+    Selector._cache[this.expression] = this.matcher;
+  },
+
+  compileXPathMatcher: function() {
+    var e = this.expression, ps = Selector.patterns,
+        x = Selector.xpath, le, m;
+
+    if (Selector._cache[e]) {
+      this.xpath = Selector._cache[e]; return;
+    }
+
+    this.matcher = ['.//*'];
+    while (e && le != e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        if (m = e.match(ps[i])) {
+          this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+            new Template(x[i]).evaluate(m));
+          e = e.replace(m[0], '');
+          break;
+        }
+      }
+    }
+
+    this.xpath = this.matcher.join('');
+    Selector._cache[this.expression] = this.xpath;
+  },
+
+  findElements: function(root) {
+    root = root || document;
+    if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+    return this.matcher(root);
+  },
+
+  match: function(element) {
+    this.tokens = [];
+
+    var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+    var le, p, m;
+
+    while (e && le !== e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        p = ps[i];
+        if (m = e.match(p)) {
+          // use the Selector.assertions methods unless the selector
+          // is too complex.
+          if (as[i]) {
+            this.tokens.push([i, Object.clone(m)]);
+            e = e.replace(m[0], '');
+          } else {
+            // reluctantly do a document-wide search
+            // and look for a match in the array
+            return this.findElements(document).include(element);
+          }
+        }
+      }
+    }
+
+    var match = true, name, matches;
+    for (var i = 0, token; token = this.tokens[i]; i++) {
+      name = token[0], matches = token[1];
+      if (!Selector.assertions[name](element, matches)) {
+        match = false; break;
+      }
+    }
+
+    return match;
+  },
+
+  toString: function() {
+    return this.expression;
+  },
+
+  inspect: function() {
+    return "#<Selector:" + this.expression.inspect() + ">";
+  }
+});
+
+Object.extend(Selector, {
+  _cache: { },
+
+  xpath: {
+    descendant:   "//*",
+    child:        "/*",
+    adjacent:     "/following-sibling::*[1]",
+    laterSibling: '/following-sibling::*',
+    tagName:      function(m) {
+      if (m[1] == '*') return '';
+      return "[local-name()='" + m[1].toLowerCase() +
+             "' or local-name()='" + m[1].toUpperCase() + "']";
+    },
+    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+    id:           "[@id='#{1}']",
+    attrPresence: "[@#{1}]",
+    attr: function(m) {
+      m[3] = m[5] || m[6];
+      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+    },
+    pseudo: function(m) {
+      var h = Selector.xpath.pseudos[m[1]];
+      if (!h) return '';
+      if (Object.isFunction(h)) return h(m);
+      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+    },
+    operators: {
+      '=':  "[@#{1}='#{3}']",
+      '!=': "[@#{1}!='#{3}']",
+      '^=': "[starts-with(@#{1}, '#{3}')]",
+      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+      '*=': "[contains(@#{1}, '#{3}')]",
+      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+    },
+    pseudos: {
+      'first-child': '[not(preceding-sibling::*)]',
+      'last-child':  '[not(following-sibling::*)]',
+      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
+      'empty':       "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+      'checked':     "[@checked]",
+      'disabled':    "[@disabled]",
+      'enabled':     "[not(@disabled)]",
+      'not': function(m) {
+        var e = m[6], p = Selector.patterns,
+            x = Selector.xpath, le, m, v;
+
+        var exclusion = [];
+        while (e && le != e && (/\S/).test(e)) {
+          le = e;
+          for (var i in p) {
+            if (m = e.match(p[i])) {
+              v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+              e = e.replace(m[0], '');
+              break;
+            }
+          }
+        }
+        return "[not(" + exclusion.join(" and ") + ")]";
+      },
+      'nth-child':      function(m) {
+        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+      },
+      'nth-last-child': function(m) {
+        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+      },
+      'nth-of-type':    function(m) {
+        return Selector.xpath.pseudos.nth("position() ", m);
+      },
+      'nth-last-of-type': function(m) {
+        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+      },
+      'first-of-type':  function(m) {
+        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+      },
+      'last-of-type':   function(m) {
+        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+      },
+      'only-of-type':   function(m) {
+        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+      },
+      nth: function(fragment, m) {
+        var mm, formula = m[6], predicate;
+        if (formula == 'even') formula = '2n+0';
+        if (formula == 'odd')  formula = '2n+1';
+        if (mm = formula.match(/^(\d+)$/)) // digit only
+          return '[' + fragment + "= " + mm[1] + ']';
+        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+          if (mm[1] == "-") mm[1] = -1;
+          var a = mm[1] ? Number(mm[1]) : 1;
+          var b = mm[2] ? Number(mm[2]) : 0;
+          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+          "((#{fragment} - #{b}) div #{a} >= 0)]";
+          return new Template(predicate).evaluate({
+            fragment: fragment, a: a, b: b });
+        }
+      }
+    }
+  },
+
+  criteria: {
+    tagName:      'n = h.tagName(n, r, "#{1}", c);   c = false;',
+    className:    'n = h.className(n, r, "#{1}", c); c = false;',
+    id:           'n = h.id(n, r, "#{1}", c);        c = false;',
+    attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
+    attr: function(m) {
+      m[3] = (m[5] || m[6]);
+      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
+    },
+    pseudo: function(m) {
+      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+    },
+    descendant:   'c = "descendant";',
+    child:        'c = "child";',
+    adjacent:     'c = "adjacent";',
+    laterSibling: 'c = "laterSibling";'
+  },
+
+  patterns: {
+    // combinators must be listed first
+    // (and descendant needs to be last combinator)
+    laterSibling: /^\s*~\s*/,
+    child:        /^\s*>\s*/,
+    adjacent:     /^\s*\+\s*/,
+    descendant:   /^\s/,
+
+    // selectors follow
+    tagName:      /^\s*(\*|[\w\-]+)(\b|$)?/,
+    id:           /^#([\w\-\*]+)(\b|$)/,
+    className:    /^\.([\w\-\*]+)(\b|$)/,
+    pseudo:       /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/,
+    attrPresence: /^\[([\w]+)\]/,
+    attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+  },
+
+  // for Selector.match and Element#match
+  assertions: {
+    tagName: function(element, matches) {
+      return matches[1].toUpperCase() == element.tagName.toUpperCase();
+    },
+
+    className: function(element, matches) {
+      return Element.hasClassName(element, matches[1]);
+    },
+
+    id: function(element, matches) {
+      return element.id === matches[1];
+    },
+
+    attrPresence: function(element, matches) {
+      return Element.hasAttribute(element, matches[1]);
+    },
+
+    attr: function(element, matches) {
+      var nodeValue = Element.readAttribute(element, matches[1]);
+      return Selector.operators[matches[2]](nodeValue, matches[3]);
+    }
+  },
+
+  handlers: {
+    // UTILITY FUNCTIONS
+    // joins two collections
+    concat: function(a, b) {
+      for (var i = 0, node; node = b[i]; i++)
+        a.push(node);
+      return a;
+    },
+
+    // marks an array of nodes for counting
+    mark: function(nodes) {
+      for (var i = 0, node; node = nodes[i]; i++)
+        node._counted = true;
+      return nodes;
+    },
+
+    unmark: function(nodes) {
+      for (var i = 0, node; node = nodes[i]; i++)
+        node._counted = undefined;
+      return nodes;
+    },
+
+    // mark each child node with its position (for nth calls)
+    // "ofType" flag indicates whether we're indexing for nth-of-type
+    // rather than nth-child
+    index: function(parentNode, reverse, ofType) {
+      parentNode._counted = true;
+      if (reverse) {
+        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+          var node = nodes[i];
+          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+        }
+      } else {
+        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+          if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+      }
+    },
+
+    // filters out duplicates and extends all nodes
+    unique: function(nodes) {
+      if (nodes.length == 0) return nodes;
+      var results = [], n;
+      for (var i = 0, l = nodes.length; i < l; i++)
+        if (!(n = nodes[i])._counted) {
+          n._counted = true;
+          results.push(Element.extend(n));
+        }
+      return Selector.handlers.unmark(results);
+    },
+
+    // COMBINATOR FUNCTIONS
+    descendant: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        h.concat(results, node.getElementsByTagName('*'));
+      return results;
+    },
+
+    child: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
+          if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+      }
+      return results;
+    },
+
+    adjacent: function(nodes) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        var next = this.nextElementSibling(node);
+        if (next) results.push(next);
+      }
+      return results;
+    },
+
+    laterSibling: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        h.concat(results, Element.nextSiblings(node));
+      return results;
+    },
+
+    nextElementSibling: function(node) {
+      while (node = node.nextSibling)
+	      if (node.nodeType == 1) return node;
+      return null;
+    },
+
+    previousElementSibling: function(node) {
+      while (node = node.previousSibling)
+        if (node.nodeType == 1) return node;
+      return null;
+    },
+
+    // TOKEN FUNCTIONS
+    tagName: function(nodes, root, tagName, combinator) {
+      tagName = tagName.toUpperCase();
+      var results = [], h = Selector.handlers;
+      if (nodes) {
+        if (combinator) {
+          // fastlane for ordinary descendant combinators
+          if (combinator == "descendant") {
+            for (var i = 0, node; node = nodes[i]; i++)
+              h.concat(results, node.getElementsByTagName(tagName));
+            return results;
+          } else nodes = this[combinator](nodes);
+          if (tagName == "*") return nodes;
+        }
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node.tagName.toUpperCase() == tagName) results.push(node);
+        return results;
+      } else return root.getElementsByTagName(tagName);
+    },
+
+    id: function(nodes, root, id, combinator) {
+      var targetNode = $(id), h = Selector.handlers;
+      if (!targetNode) return [];
+      if (!nodes && root == document) return [targetNode];
+      if (nodes) {
+        if (combinator) {
+          if (combinator == 'child') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (targetNode.parentNode == node) return [targetNode];
+          } else if (combinator == 'descendant') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (Element.descendantOf(targetNode, node)) return [targetNode];
+          } else if (combinator == 'adjacent') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (Selector.handlers.previousElementSibling(targetNode) == node)
+                return [targetNode];
+          } else nodes = h[combinator](nodes);
+        }
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node == targetNode) return [targetNode];
+        return [];
+      }
+      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+    },
+
+    className: function(nodes, root, className, combinator) {
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      return Selector.handlers.byClassName(nodes, root, className);
+    },
+
+    byClassName: function(nodes, root, className) {
+      if (!nodes) nodes = Selector.handlers.descendant([root]);
+      var needle = ' ' + className + ' ';
+      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+        nodeClassName = node.className;
+        if (nodeClassName.length == 0) continue;
+        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+          results.push(node);
+      }
+      return results;
+    },
+
+    attrPresence: function(nodes, root, attr) {
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      var results = [];
+      for (var i = 0, node; node = nodes[i]; i++)
+        if (Element.hasAttribute(node, attr)) results.push(node);
+      return results;
+    },
+
+    attr: function(nodes, root, attr, value, operator) {
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      var handler = Selector.operators[operator], results = [];
+      for (var i = 0, node; node = nodes[i]; i++) {
+        var nodeValue = Element.readAttribute(node, attr);
+        if (nodeValue === null) continue;
+        if (handler(nodeValue, value)) results.push(node);
+      }
+      return results;
+    },
+
+    pseudo: function(nodes, name, value, root, combinator) {
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      return Selector.pseudos[name](nodes, value, root);
+    }
+  },
+
+  pseudos: {
+    'first-child': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        if (Selector.handlers.previousElementSibling(node)) continue;
+          results.push(node);
+      }
+      return results;
+    },
+    'last-child': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        if (Selector.handlers.nextElementSibling(node)) continue;
+          results.push(node);
+      }
+      return results;
+    },
+    'only-child': function(nodes, value, root) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+          results.push(node);
+      return results;
+    },
+    'nth-child':        function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root);
+    },
+    'nth-last-child':   function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, true);
+    },
+    'nth-of-type':      function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, false, true);
+    },
+    'nth-last-of-type': function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, true, true);
+    },
+    'first-of-type':    function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, "1", root, false, true);
+    },
+    'last-of-type':     function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, "1", root, true, true);
+    },
+    'only-of-type':     function(nodes, formula, root) {
+      var p = Selector.pseudos;
+      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+    },
+
+    // handles the an+b logic
+    getIndices: function(a, b, total) {
+      if (a == 0) return b > 0 ? [b] : [];
+      return $R(1, total).inject([], function(memo, i) {
+        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+        return memo;
+      });
+    },
+
+    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+    nth: function(nodes, formula, root, reverse, ofType) {
+      if (nodes.length == 0) return [];
+      if (formula == 'even') formula = '2n+0';
+      if (formula == 'odd')  formula = '2n+1';
+      var h = Selector.handlers, results = [], indexed = [], m;
+      h.mark(nodes);
+      for (var i = 0, node; node = nodes[i]; i++) {
+        if (!node.parentNode._counted) {
+          h.index(node.parentNode, reverse, ofType);
+          indexed.push(node.parentNode);
+        }
+      }
+      if (formula.match(/^\d+$/)) { // just a number
+        formula = Number(formula);
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node.nodeIndex == formula) results.push(node);
+      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+        if (m[1] == "-") m[1] = -1;
+        var a = m[1] ? Number(m[1]) : 1;
+        var b = m[2] ? Number(m[2]) : 0;
+        var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+          for (var j = 0; j < l; j++)
+            if (node.nodeIndex == indices[j]) results.push(node);
+        }
+      }
+      h.unmark(nodes);
+      h.unmark(indexed);
+      return results;
+    },
+
+    'empty': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        // IE treats comments as element nodes
+        if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+        results.push(node);
+      }
+      return results;
+    },
+
+    'not': function(nodes, selector, root) {
+      var h = Selector.handlers, selectorType, m;
+      var exclusions = new Selector(selector).findElements(root);
+      h.mark(exclusions);
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!node._counted) results.push(node);
+      h.unmark(exclusions);
+      return results;
+    },
+
+    'enabled': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!node.disabled) results.push(node);
+      return results;
+    },
+
+    'disabled': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (node.disabled) results.push(node);
+      return results;
+    },
+
+    'checked': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (node.checked) results.push(node);
+      return results;
+    }
+  },
+
+  operators: {
+    '=':  function(nv, v) { return nv == v; },
+    '!=': function(nv, v) { return nv != v; },
+    '^=': function(nv, v) { return nv.startsWith(v); },
+    '$=': function(nv, v) { return nv.endsWith(v); },
+    '*=': function(nv, v) { return nv.include(v); },
+    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+    '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+  },
+
+  matchElements: function(elements, expression) {
+    var matches = new Selector(expression).findElements(), h = Selector.handlers;
+    h.mark(matches);
+    for (var i = 0, results = [], element; element = elements[i]; i++)
+      if (element._counted) results.push(element);
+    h.unmark(matches);
+    return results;
+  },
+
+  findElement: function(elements, expression, index) {
+    if (Object.isNumber(expression)) {
+      index = expression; expression = false;
+    }
+    return Selector.matchElements(elements, expression || '*')[index || 0];
+  },
+
+  findChildElements: function(element, expressions) {
+    var exprs = expressions.join(','), expressions = [];
+    exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+      expressions.push(m[1].strip());
+    });
+    var results = [], h = Selector.handlers;
+    for (var i = 0, l = expressions.length, selector; i < l; i++) {
+      selector = new Selector(expressions[i].strip());
+      h.concat(results, selector.findElements(element));
+    }
+    return (l > 1) ? h.unique(results) : results;
+  }
+});
+
+function $$() {
+  return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+  reset: function(form) {
+    $(form).reset();
+    return form;
+  },
+
+  serializeElements: function(elements, options) {
+    if (typeof options != 'object') options = { hash: !!options };
+    else if (options.hash === undefined) options.hash = true;
+    var key, value, submitted = false, submit = options.submit;
+
+    var data = elements.inject({ }, function(result, element) {
+      if (!element.disabled && element.name) {
+        key = element.name; value = $(element).getValue();
+        if (value != null && (element.type != 'submit' || (!submitted &&
+            submit !== false && (!submit || key == submit) && (submitted = true)))) {
+          if (key in result) {
+            // a key is already present; construct an array of values
+            if (!Object.isArray(result[key])) result[key] = [result[key]];
+            result[key].push(value);
+          }
+          else result[key] = value;
+        }
+      }
+      return result;
+    });
+
+    return options.hash ? data : Object.toQueryString(data);
+  }
+};
+
+Form.Methods = {
+  serialize: function(form, options) {
+    return Form.serializeElements(Form.getElements(form), options);
+  },
+
+  getElements: function(form) {
+    return $A($(form).getElementsByTagName('*')).inject([],
+      function(elements, child) {
+        if (Form.Element.Serializers[child.tagName.toLowerCase()])
+          elements.push(Element.extend(child));
+        return elements;
+      }
+    );
+  },
+
+  getInputs: function(form, typeName, name) {
+    form = $(form);
+    var inputs = form.getElementsByTagName('input');
+
+    if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+      var input = inputs[i];
+      if ((typeName && input.type != typeName) || (name && input.name != name))
+        continue;
+      matchingInputs.push(Element.extend(input));
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    form = $(form);
+    Form.getElements(form).invoke('disable');
+    return form;
+  },
+
+  enable: function(form) {
+    form = $(form);
+    Form.getElements(form).invoke('enable');
+    return form;
+  },
+
+  findFirstElement: function(form) {
+    var elements = $(form).getElements().findAll(function(element) {
+      return 'hidden' != element.type && !element.disabled;
+    });
+    var firstByIndex = elements.findAll(function(element) {
+      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+    }).sortBy(function(element) { return element.tabIndex }).first();
+
+    return firstByIndex ? firstByIndex : elements.find(function(element) {
+      return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+    });
+  },
+
+  focusFirstElement: function(form) {
+    form = $(form);
+    form.findFirstElement().activate();
+    return form;
+  },
+
+  request: function(form, options) {
+    form = $(form), options = Object.clone(options || { });
+
+    var params = options.parameters, action = form.readAttribute('action') || '';
+    if (action.blank()) action = window.location.href;
+    options.parameters = form.serialize(true);
+
+    if (params) {
+      if (Object.isString(params)) params = params.toQueryParams();
+      Object.extend(options.parameters, params);
+    }
+
+    if (form.hasAttribute('method') && !options.method)
+      options.method = form.method;
+
+    return new Ajax.Request(action, options);
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+  focus: function(element) {
+    $(element).focus();
+    return element;
+  },
+
+  select: function(element) {
+    $(element).select();
+    return element;
+  }
+};
+
+Form.Element.Methods = {
+  serialize: function(element) {
+    element = $(element);
+    if (!element.disabled && element.name) {
+      var value = element.getValue();
+      if (value != undefined) {
+        var pair = { };
+        pair[element.name] = value;
+        return Object.toQueryString(pair);
+      }
+    }
+    return '';
+  },
+
+  getValue: function(element) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    return Form.Element.Serializers[method](element);
+  },
+
+  setValue: function(element, value) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    Form.Element.Serializers[method](element, value);
+    return element;
+  },
+
+  clear: function(element) {
+    $(element).value = '';
+    return element;
+  },
+
+  present: function(element) {
+    return $(element).value != '';
+  },
+
+  activate: function(element) {
+    element = $(element);
+    try {
+      element.focus();
+      if (element.select && (element.tagName.toLowerCase() != 'input' ||
+          !['button', 'reset', 'submit'].include(element.type)))
+        element.select();
+    } catch (e) { }
+    return element;
+  },
+
+  disable: function(element) {
+    element = $(element);
+    element.blur();
+    element.disabled = true;
+    return element;
+  },
+
+  enable: function(element) {
+    element = $(element);
+    element.disabled = false;
+    return element;
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+  input: function(element, value) {
+    switch (element.type.toLowerCase()) {
+      case 'checkbox':
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element, value);
+      default:
+        return Form.Element.Serializers.textarea(element, value);
+    }
+  },
+
+  inputSelector: function(element, value) {
+    if (value === undefined) return element.checked ? element.value : null;
+    else element.checked = !!value;
+  },
+
+  textarea: function(element, value) {
+    if (value === undefined) return element.value;
+    else element.value = value;
+  },
+
+  select: function(element, index) {
+    if (index === undefined)
+      return this[element.type == 'select-one' ?
+        'selectOne' : 'selectMany'](element);
+    else {
+      var opt, value, single = !Object.isArray(index);
+      for (var i = 0, length = element.length; i < length; i++) {
+        opt = element.options[i];
+        value = this.optionValue(opt);
+        if (single) {
+          if (value == index) {
+            opt.selected = true;
+            return;
+          }
+        }
+        else opt.selected = index.include(value);
+      }
+    }
+  },
+
+  selectOne: function(element) {
+    var index = element.selectedIndex;
+    return index >= 0 ? this.optionValue(element.options[index]) : null;
+  },
+
+  selectMany: function(element) {
+    var values, length = element.length;
+    if (!length) return null;
+
+    for (var i = 0, values = []; i < length; i++) {
+      var opt = element.options[i];
+      if (opt.selected) values.push(this.optionValue(opt));
+    }
+    return values;
+  },
+
+  optionValue: function(opt) {
+    // extend element because hasAttribute may not be native
+    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+  initialize: function($super, element, frequency, callback) {
+    $super(callback, frequency);
+    this.element   = $(element);
+    this.lastValue = this.getValue();
+  },
+
+  execute: function() {
+    var value = this.getValue();
+    if (Object.isString(this.lastValue) && Object.isString(value) ?
+        this.lastValue != value : String(this.lastValue) != String(value)) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+  initialize: function(element, callback) {
+    this.element  = $(element);
+    this.callback = callback;
+
+    this.lastValue = this.getValue();
+    if (this.element.tagName.toLowerCase() == 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+
+  onElementEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  },
+
+  registerFormCallbacks: function() {
+    Form.getElements(this.element).each(this.registerCallback, this);
+  },
+
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox':
+        case 'radio':
+          Event.observe(element, 'click', this.onElementEvent.bind(this));
+          break;
+        default:
+          Event.observe(element, 'change', this.onElementEvent.bind(this));
+          break;
+      }
+    }
+  }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+  KEY_HOME:     36,
+  KEY_END:      35,
+  KEY_PAGEUP:   33,
+  KEY_PAGEDOWN: 34,
+  KEY_INSERT:   45,
+
+  cache: { },
+
+  relatedTarget: function(event) {
+    var element;
+    switch(event.type) {
+      case 'mouseover': element = event.fromElement; break;
+      case 'mouseout':  element = event.toElement;   break;
+      default: return null;
+    }
+    return Element.extend(element);
+  }
+});
+
+Event.Methods = (function() {
+  var isButton;
+
+  if (Prototype.Browser.IE) {
+    var buttonMap = { 0: 1, 1: 4, 2: 2 };
+    isButton = function(event, code) {
+      return event.button == buttonMap[code];
+    };
+
+  } else if (Prototype.Browser.WebKit) {
+    isButton = function(event, code) {
+      switch (code) {
+        case 0: return event.which == 1 && !event.metaKey;
+        case 1: return event.which == 1 && event.metaKey;
+        default: return false;
+      }
+    };
+
+  } else {
+    isButton = function(event, code) {
+      return event.which ? (event.which === code + 1) : (event.button === code);
+    };
+  }
+
+  return {
+    isLeftClick:   function(event) { return isButton(event, 0) },
+    isMiddleClick: function(event) { return isButton(event, 1) },
+    isRightClick:  function(event) { return isButton(event, 2) },
+
+    element: function(event) {
+      var node = Event.extend(event).target;
+      return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+    },
+
+    findElement: function(event, expression) {
+      var element = Event.element(event);
+      return element.match(expression) ? element : element.up(expression);
+    },
+
+    pointer: function(event) {
+      return {
+        x: event.pageX || (event.clientX +
+          (document.documentElement.scrollLeft || document.body.scrollLeft)),
+        y: event.pageY || (event.clientY +
+          (document.documentElement.scrollTop || document.body.scrollTop))
+      };
+    },
+
+    pointerX: function(event) { return Event.pointer(event).x },
+    pointerY: function(event) { return Event.pointer(event).y },
+
+    stop: function(event) {
+      Event.extend(event);
+      event.preventDefault();
+      event.stopPropagation();
+      event.stopped = true;
+    }
+  };
+})();
+
+Event.extend = (function() {
+  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+    m[name] = Event.Methods[name].methodize();
+    return m;
+  });
+
+  if (Prototype.Browser.IE) {
+    Object.extend(methods, {
+      stopPropagation: function() { this.cancelBubble = true },
+      preventDefault:  function() { this.returnValue = false },
+      inspect: function() { return "[object Event]" }
+    });
+
+    return function(event) {
+      if (!event) return false;
+      if (event._extendedByPrototype) return event;
+
+      event._extendedByPrototype = Prototype.emptyFunction;
+      var pointer = Event.pointer(event);
+      Object.extend(event, {
+        target: event.srcElement,
+        relatedTarget: Event.relatedTarget(event),
+        pageX:  pointer.x,
+        pageY:  pointer.y
+      });
+      return Object.extend(event, methods);
+    };
+
+  } else {
+    Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+    Object.extend(Event.prototype, methods);
+    return Prototype.K;
+  }
+})();
+
+Object.extend(Event, (function() {
+  var cache = Event.cache;
+
+  function getEventID(element) {
+    if (element._eventID) return element._eventID;
+    arguments.callee.id = arguments.callee.id || 1;
+    return element._eventID = ++arguments.callee.id;
+  }
+
+  function getDOMEventName(eventName) {
+    if (eventName && eventName.include(':')) return "dataavailable";
+    return eventName;
+  }
+
+  function getCacheForID(id) {
+    return cache[id] = cache[id] || { };
+  }
+
+  function getWrappersForEventName(id, eventName) {
+    var c = getCacheForID(id);
+    return c[eventName] = c[eventName] || [];
+  }
+
+  function createWrapper(element, eventName, handler) {
+    var id = getEventID(element);
+    var c = getWrappersForEventName(id, eventName);
+    if (c.pluck("handler").include(handler)) return false;
+
+    var wrapper = function(event) {
+      if (!Event || !Event.extend ||
+        (event.eventName && event.eventName != eventName))
+          return false;
+
+      Event.extend(event);
+      handler.call(element, event)
+    };
+
+    wrapper.handler = handler;
+    c.push(wrapper);
+    return wrapper;
+  }
+
+  function findWrapper(id, eventName, handler) {
+    var c = getWrappersForEventName(id, eventName);
+    return c.find(function(wrapper) { return wrapper.handler == handler });
+  }
+
+  function destroyWrapper(id, eventName, handler) {
+    var c = getCacheForID(id);
+    if (!c[eventName]) return false;
+    c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+  }
+
+  function destroyCache() {
+    for (var id in cache)
+      for (var eventName in cache[id])
+        cache[id][eventName] = null;
+  }
+
+  if (window.attachEvent) {
+    window.attachEvent("onunload", destroyCache);
+  }
+
+  return {
+    observe: function(element, eventName, handler) {
+      element = $(element);
+      var name = getDOMEventName(eventName);
+
+      var wrapper = createWrapper(element, eventName, handler);
+      if (!wrapper) return element;
+
+      if (element.addEventListener) {
+        element.addEventListener(name, wrapper, false);
+      } else {
+        element.attachEvent("on" + name, wrapper);
+      }
+
+      return element;
+    },
+
+    stopObserving: function(element, eventName, handler) {
+      element = $(element);
+      var id = getEventID(element), name = getDOMEventName(eventName);
+
+      if (!handler && eventName) {
+        getWrappersForEventName(id, eventName).each(function(wrapper) {
+          element.stopObserving(eventName, wrapper.handler);
+        });
+        return element;
+
+      } else if (!eventName) {
+        Object.keys(getCacheForID(id)).each(function(eventName) {
+          element.stopObserving(eventName);
+        });
+        return element;
+      }
+
+      var wrapper = findWrapper(id, eventName, handler);
+      if (!wrapper) return element;
+
+      if (element.removeEventListener) {
+        element.removeEventListener(name, wrapper, false);
+      } else {
+        element.detachEvent("on" + name, wrapper);
+      }
+
+      destroyWrapper(id, eventName, handler);
+
+      return element;
+    },
+
+    fire: function(element, eventName, memo) {
+      element = $(element);
+      if (element == document && document.createEvent && !element.dispatchEvent)
+        element = document.documentElement;
+
+      if (document.createEvent) {
+        var event = document.createEvent("HTMLEvents");
+        event.initEvent("dataavailable", true, true);
+      } else {
+        var event = document.createEventObject();
+        event.eventType = "ondataavailable";
+      }
+
+      event.eventName = eventName;
+      event.memo = memo || { };
+
+      if (document.createEvent) {
+        element.dispatchEvent(event);
+      } else {
+        element.fireEvent(event.eventType, event);
+      }
+
+      return event;
+    }
+  };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+  fire:          Event.fire,
+  observe:       Event.observe,
+  stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+  fire:          Element.Methods.fire.methodize(),
+  observe:       Element.Methods.observe.methodize(),
+  stopObserving: Element.Methods.stopObserving.methodize()
+});
+
+(function() {
+  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+     Matthias Miller, Dean Edwards and John Resig. */
+
+  var timer, fired = false;
+
+  function fireContentLoadedEvent() {
+    if (fired) return;
+    if (timer) window.clearInterval(timer);
+    document.fire("dom:loaded");
+    fired = true;
+  }
+
+  if (document.addEventListener) {
+    if (Prototype.Browser.WebKit) {
+      timer = window.setInterval(function() {
+        if (/loaded|complete/.test(document.readyState))
+          fireContentLoadedEvent();
+      }, 0);
+
+      Event.observe(window, "load", fireContentLoadedEvent);
+
+    } else {
+      document.addEventListener("DOMContentLoaded",
+        fireContentLoadedEvent, false);
+    }
+
+  } else {
+    document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+    $("__onDOMContentLoaded").onreadystatechange = function() {
+      if (this.readyState == "complete") {
+        this.onreadystatechange = null;
+        fireContentLoadedEvent();
+      }
+    };
+  }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+  Before: function(element, content) {
+    return Element.insert(element, {before:content});
+  },
+
+  Top: function(element, content) {
+    return Element.insert(element, {top:content});
+  },
+
+  Bottom: function(element, content) {
+    return Element.insert(element, {bottom:content});
+  },
+
+  After: function(element, content) {
+    return Element.insert(element, {after:content});
+  }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false,
+
+  // must be called before calling withinIncludingScrolloffset, every time the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =  window.pageXOffset
+                || document.documentElement.scrollLeft
+                || document.body.scrollLeft
+                || 0;
+    this.deltaY =  window.pageYOffset
+                || document.documentElement.scrollTop
+                || document.body.scrollTop
+                || 0;
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp = x;
+    this.ycomp = y;
+    this.offset = Element.cumulativeOffset(element);
+
+    return (y >= this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >= this.offset[0] &&
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache = Element.cumulativeScrollOffset(element);
+
+    this.xcomp = x + offsetcache[0] - this.deltaX;
+    this.ycomp = y + offsetcache[1] - this.deltaY;
+    this.offset = Element.cumulativeOffset(element);
+
+    return (this.ycomp >= this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >= this.offset[0] &&
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) {
+    if (!mode) return 0;
+    if (mode == 'vertical')
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+        element.offsetHeight;
+    if (mode == 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+        element.offsetWidth;
+  },
+
+  // Deprecation layer -- use newer Element methods now (1.5.2).
+
+  cumulativeOffset: Element.Methods.cumulativeOffset,
+
+  positionedOffset: Element.Methods.positionedOffset,
+
+  absolutize: function(element) {
+    Position.prepare();
+    return Element.absolutize(element);
+  },
+
+  relativize: function(element) {
+    Position.prepare();
+    return Element.relativize(element);
+  },
+
+  realOffset: Element.Methods.cumulativeScrollOffset,
+
+  offsetParent: Element.Methods.getOffsetParent,
+
+  page: Element.Methods.viewportOffset,
+
+  clone: function(source, target, options) {
+    options = options || { };
+    return Element.clonePosition(target, source, options);
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+  function iter(name) {
+    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+  }
+
+  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+  function(element, className) {
+    className = className.toString().strip();
+    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+  } : function(element, className) {
+    className = className.toString().strip();
+    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+    if (!classNames && !className) return elements;
+
+    var nodes = $(element).getElementsByTagName('*');
+    className = ' ' + className + ' ';
+
+    for (var i = 0, child, cn; child = nodes[i]; i++) {
+      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+          (classNames && classNames.all(function(name) {
+            return !name.toString().blank() && cn.include(' ' + name + ' ');
+          }))))
+        elements.push(Element.extend(child));
+    }
+    return elements;
+  };
+
+  return function(className, parentElement) {
+    return $(parentElement || document.body).getElementsByClassName(className);
+  };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+  initialize: function(element) {
+    this.element = $(element);
+  },
+
+  _each: function(iterator) {
+    this.element.className.split(/\s+/).select(function(name) {
+      return name.length > 0;
+    })._each(iterator);
+  },
+
+  set: function(className) {
+    this.element.className = className;
+  },
+
+  add: function(classNameToAdd) {
+    if (this.include(classNameToAdd)) return;
+    this.set($A(this).concat(classNameToAdd).join(' '));
+  },
+
+  remove: function(classNameToRemove) {
+    if (!this.include(classNameToRemove)) return;
+    this.set($A(this).without(classNameToRemove).join(' '));
+  },
+
+  toString: function() {
+    return $A(this).join(' ');
+  }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods();
Index: branches/features/taskProcedureRework/web-app/js/prototype/rico.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/rico.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/rico.js	(revision 753)
@@ -0,0 +1,2691 @@
+/**
+  *
+  *  Copyright 2005 Sabre Airline Solutions
+  *
+  *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
+  *  file except in compliance with the License. You may obtain a copy of the License at
+  *
+  *         http://www.apache.org/licenses/LICENSE-2.0
+  *
+  *  Unless required by applicable law or agreed to in writing, software distributed under the
+  *  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+  *  either express or implied. See the License for the specific language governing permissions
+  *  and limitations under the License.
+  **/
+
+
+//-------------------- rico.js
+var Rico = {
+  Version: '1.1-beta2'
+}
+
+Rico.ArrayExtensions = new Array();
+
+if (Object.prototype.extend) {
+   // in prototype.js...
+   Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Object.prototype.extend;
+}
+
+if (Array.prototype.push) {
+   // in prototype.js...
+   Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.push;
+}
+
+if (!Array.prototype.remove) {
+   Array.prototype.remove = function(dx) {
+      if( isNaN(dx) || dx > this.length )
+         return false;
+      for( var i=0,n=0; i<this.length; i++ )
+         if( i != dx )
+            this[n++]=this[i];
+      this.length-=1;
+   };
+  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.remove;
+}
+
+if (!Array.prototype.removeItem) {
+   Array.prototype.removeItem = function(item) {
+      for ( var i = 0 ; i < this.length ; i++ )
+         if ( this[i] == item ) {
+            this.remove(i);
+            break;
+         }
+   };
+  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.removeItem;
+}
+
+if (!Array.prototype.indices) {
+   Array.prototype.indices = function() {
+      var indexArray = new Array();
+      for ( index in this ) {
+         var ignoreThis = false;
+         for ( var i = 0 ; i < Rico.ArrayExtensions.length ; i++ ) {
+            if ( this[index] == Rico.ArrayExtensions[i] ) {
+               ignoreThis = true;
+               break;
+            }
+         }
+         if ( !ignoreThis )
+            indexArray[ indexArray.length ] = index;
+      }
+      return indexArray;
+   }
+  Rico.ArrayExtensions[ Rico.ArrayExtensions.length ] = Array.prototype.indices;
+}
+
+// Create the loadXML method and xml getter for Mozilla
+if ( window.DOMParser &&
+	  window.XMLSerializer &&
+	  window.Node && Node.prototype && Node.prototype.__defineGetter__ ) {
+
+   if (!Document.prototype.loadXML) {
+      Document.prototype.loadXML = function (s) {
+         var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
+         while (this.hasChildNodes())
+            this.removeChild(this.lastChild);
+
+         for (var i = 0; i < doc2.childNodes.length; i++) {
+            this.appendChild(this.importNode(doc2.childNodes[i], true));
+         }
+      };
+	}
+
+	Document.prototype.__defineGetter__( "xml",
+	   function () {
+		   return (new XMLSerializer()).serializeToString(this);
+	   }
+	 );
+}
+
+document.getElementsByTagAndClassName = function(tagName, className) {
+  if ( tagName == null )
+     tagName = '*';
+
+  var children = document.getElementsByTagName(tagName) || document.all;
+  var elements = new Array();
+
+  if ( className == null )
+    return children;
+
+  for (var i = 0; i < children.length; i++) {
+    var child = children[i];
+    var classNames = child.className.split(' ');
+    for (var j = 0; j < classNames.length; j++) {
+      if (classNames[j] == className) {
+        elements.push(child);
+        break;
+      }
+    }
+  }
+
+  return elements;
+}
+
+
+//-------------------- ricoAccordion.js
+
+Rico.Accordion = Class.create();
+
+Rico.Accordion.prototype = {
+
+   initialize: function(container, options) {
+      this.container            = $(container);
+      this.lastExpandedTab      = null;
+      this.accordionTabs        = new Array();
+      this.setOptions(options);
+      this._attachBehaviors();
+
+      this.container.style.borderBottom = '1px solid ' + this.options.borderColor;
+
+      // set the initial visual state...
+      for ( var i=1 ; i < this.accordionTabs.length ; i++ )
+      {
+         this.accordionTabs[i].collapse();
+         this.accordionTabs[i].content.style.display = 'none';
+      }
+      this.lastExpandedTab = this.accordionTabs[0];
+      this.lastExpandedTab.content.style.height = this.options.panelHeight + "px";
+      this.lastExpandedTab.showExpanded();
+      this.lastExpandedTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
+   },
+
+   setOptions: function(options) {
+      this.options = {
+         expandedBg          : '#63699c',
+         hoverBg             : '#63699c',
+         collapsedBg         : '#6b79a5',
+         expandedTextColor   : '#ffffff',
+         expandedFontWeight  : 'bold',
+         hoverTextColor      : '#ffffff',
+         collapsedTextColor  : '#ced7ef',
+         collapsedFontWeight : 'normal',
+         hoverTextColor      : '#ffffff',
+         borderColor         : '#1f669b',
+         panelHeight         : 200,
+         onHideTab           : null,
+         onShowTab           : null
+      }.extend(options || {});
+   },
+
+   showTabByIndex: function( anIndex, animate ) {
+      var doAnimate = arguments.length == 1 ? true : animate;
+      this.showTab( this.accordionTabs[anIndex], doAnimate );
+   },
+
+   showTab: function( accordionTab, animate ) {
+
+      var doAnimate = arguments.length == 1 ? true : animate;
+
+      if ( this.options.onHideTab )
+         this.options.onHideTab(this.lastExpandedTab);
+
+      this.lastExpandedTab.showCollapsed(); 
+      var accordion = this;
+      var lastExpandedTab = this.lastExpandedTab;
+
+      this.lastExpandedTab.content.style.height = (this.options.panelHeight - 1) + 'px';
+      accordionTab.content.style.display = '';
+
+      accordionTab.titleBar.style.fontWeight = this.options.expandedFontWeight;
+
+      if ( doAnimate ) {
+         new Effect.AccordionSize( this.lastExpandedTab.content,
+                                   accordionTab.content,
+                                   1,
+                                   this.options.panelHeight,
+                                   100, 10,
+                                   { complete: function() {accordion.showTabDone(lastExpandedTab)} } );
+         this.lastExpandedTab = accordionTab;
+      }
+      else {
+         this.lastExpandedTab.content.style.height = "1px";
+         accordionTab.content.style.height = this.options.panelHeight + "px";
+         this.lastExpandedTab = accordionTab;
+         this.showTabDone(lastExpandedTab);
+      }
+   },
+
+   showTabDone: function(collapsedTab) {
+      collapsedTab.content.style.display = 'none';
+      this.lastExpandedTab.showExpanded();
+      if ( this.options.onShowTab )
+         this.options.onShowTab(this.lastExpandedTab);
+   },
+
+   _attachBehaviors: function() {
+      var panels = this._getDirectChildrenByTag(this.container, 'DIV');
+      for ( var i = 0 ; i < panels.length ; i++ ) {
+
+         var tabChildren = this._getDirectChildrenByTag(panels[i],'DIV');
+         if ( tabChildren.length != 2 )
+            continue; // unexpected
+
+         var tabTitleBar   = tabChildren[0];
+         var tabContentBox = tabChildren[1];
+         this.accordionTabs.push( new Rico.Accordion.Tab(this,tabTitleBar,tabContentBox) );
+      }
+   },
+
+   _getDirectChildrenByTag: function(e, tagName) {
+      var kids = new Array();
+      var allKids = e.childNodes;
+      for( var i = 0 ; i < allKids.length ; i++ )
+         if ( allKids[i] && allKids[i].tagName && allKids[i].tagName == tagName )
+            kids.push(allKids[i]);
+      return kids;
+   }
+
+};
+
+Rico.Accordion.Tab = Class.create();
+
+Rico.Accordion.Tab.prototype = {
+
+   initialize: function(accordion, titleBar, content) {
+      this.accordion = accordion;
+      this.titleBar  = titleBar;
+      this.content   = content;
+      this._attachBehaviors();
+   },
+
+   collapse: function() {
+      this.showCollapsed();
+      this.content.style.height = "1px";
+   },
+
+   showCollapsed: function() {
+      this.expanded = false;
+      this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
+      this.titleBar.style.color           = this.accordion.options.collapsedTextColor;
+      this.titleBar.style.fontWeight      = this.accordion.options.collapsedFontWeight;
+      this.content.style.overflow = "hidden";
+   },
+
+   showExpanded: function() {
+      this.expanded = true;
+      this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
+      this.titleBar.style.color           = this.accordion.options.expandedTextColor;
+      this.content.style.overflow         = "visible";
+   },
+
+   titleBarClicked: function(e) {
+      if ( this.accordion.lastExpandedTab == this )
+         return;
+      this.accordion.showTab(this);
+   },
+
+   hover: function(e) {
+		this.titleBar.style.backgroundColor = this.accordion.options.hoverBg;
+		this.titleBar.style.color           = this.accordion.options.hoverTextColor;
+   },
+
+   unhover: function(e) {
+      if ( this.expanded ) {
+         this.titleBar.style.backgroundColor = this.accordion.options.expandedBg;
+         this.titleBar.style.color           = this.accordion.options.expandedTextColor;
+      }
+      else {
+         this.titleBar.style.backgroundColor = this.accordion.options.collapsedBg;
+         this.titleBar.style.color           = this.accordion.options.collapsedTextColor;
+      }
+   },
+
+   _attachBehaviors: function() {
+      this.content.style.border = "1px solid " + this.accordion.options.borderColor;
+      this.content.style.borderTopWidth    = "0px";
+      this.content.style.borderBottomWidth = "0px";
+      this.content.style.margin            = "0px";
+
+      this.titleBar.onclick     = this.titleBarClicked.bindAsEventListener(this);
+      this.titleBar.onmouseover = this.hover.bindAsEventListener(this);
+      this.titleBar.onmouseout  = this.unhover.bindAsEventListener(this);
+   }
+
+};
+
+
+//-------------------- ricoAjaxEngine.js
+
+Rico.AjaxEngine = Class.create();
+
+Rico.AjaxEngine.prototype = {
+
+   initialize: function() {
+      this.ajaxElements = new Array();
+      this.ajaxObjects  = new Array();
+      this.requestURLS  = new Array();
+   },
+
+   registerAjaxElement: function( anId, anElement ) {
+      if ( arguments.length == 1 )
+         anElement = $(anId);
+      this.ajaxElements[anId] = anElement;
+   },
+
+   registerAjaxObject: function( anId, anObject ) {
+      this.ajaxObjects[anId] = anObject;
+   },
+
+   registerRequest: function (requestLogicalName, requestURL) {
+      this.requestURLS[requestLogicalName] = requestURL;
+   },
+
+   sendRequest: function(requestName) {
+      var requestURL = this.requestURLS[requestName];
+      if ( requestURL == null )
+         return;
+
+      var queryString = "";
+      
+      if ( arguments.length > 1 ) {
+      	 if(typeof(arguments[1]) == "object" && arguments[1].length != undefined) {
+	      	 queryString = this._createQueryString(arguments[1], 0);
+      	 }
+      	 else {
+	         queryString = this._createQueryString(arguments, 1);
+	     }         
+       }
+             
+      new Ajax.Request(requestURL, this._requestOptions(queryString));
+   },
+
+   sendRequestWithData: function(requestName, xmlDocument) {
+      var requestURL = this.requestURLS[requestName];
+      if ( requestURL == null )
+         return;
+
+      var queryString = "";
+      if ( arguments.length > 2 ) {
+      	 if(typeof(arguments[2]) == "object" && arguments[2].length != undefined) {
+	      	 queryString = this._createQueryString(arguments[2], 0);
+      	 }
+      	 else {
+	         queryString = this._createQueryString(arguments, 2);
+	     }         
+       }             
+
+      new Ajax.Request(requestURL + "?" + queryString, this._requestOptions(null,xmlDocument));
+   },
+
+   sendRequestAndUpdate: function(requestName,container,options) {
+      var requestURL = this.requestURLS[requestName];
+      if ( requestURL == null )
+         return;
+
+      var queryString = "";
+      if ( arguments.length > 3 ) {
+      	 if(typeof(arguments[3]) == "object" && arguments[3].length != undefined) {
+	      	 queryString = this._createQueryString(arguments[3], 0);
+      	 }
+      	 else {
+	         queryString = this._createQueryString(arguments, 3);
+	     }         
+       }  
+             
+      var updaterOptions = this._requestOptions(queryString);
+      updaterOptions.onComplete = null;
+      updaterOptions.extend(options);
+
+      new Ajax.Updater(container, requestURL, updaterOptions);
+   },
+
+   sendRequestWithDataAndUpdate: function(requestName,xmlDocument,container,options) {
+      var requestURL = this.requestURLS[requestName];
+      if ( requestURL == null )
+         return;
+
+      var queryString = "";
+      if ( arguments.length > 4 ) {
+      	 if(typeof(arguments[4]) == "object" && arguments[4].length != undefined) {
+	      	 queryString = this._createQueryString(arguments[4], 0);
+      	 }
+      	 else {
+	         queryString = this._createQueryString(arguments, 4);
+	     }         
+       }
+
+
+      var updaterOptions = this._requestOptions(queryString,xmlDocument);
+      updaterOptions.onComplete = null;
+      updaterOptions.extend(options);
+
+      new Ajax.Updater(container, requestURL + "?" + queryString, updaterOptions);
+   },
+
+   // Private -- not part of intended engine API --------------------------------------------------------------------
+
+   _requestOptions: function(queryString,xmlDoc) {
+      var self = this;
+
+      var requestHeaders = ['X-Rico-Version', Rico.Version ];
+      var sendMethod = "post"
+      if ( arguments[1] )
+         requestHeaders.push( 'Content-type', 'text/xml' );
+      else
+         sendMethod = "get";
+
+      return { requestHeaders: requestHeaders,
+               parameters:     queryString,
+               postBody:       arguments[1] ? xmlDoc : null,
+               method:         sendMethod,
+               onComplete:     self._onRequestComplete.bind(self) };
+   },
+
+   _createQueryString: function( theArgs, offset ) {
+   	  var self = this;
+      var queryString = ""
+      for ( var i = offset ; i < theArgs.length ; i++ ) {
+          if ( i != offset )
+            queryString += "&";
+
+          var anArg = theArgs[i];
+                  
+          if ( anArg.name != undefined && anArg.value != undefined ) {
+            queryString += anArg.name +  "=" + escape(anArg.value);
+          }
+          else {
+             var ePos  = anArg.indexOf('=');
+             var argName  = anArg.substring( 0, ePos );
+             var argValue = anArg.substring( ePos + 1 );
+             queryString += argName + "=" + escape(argValue);
+          }
+      }
+
+      return queryString;
+   },
+   _onRequestComplete : function(request) {
+
+      //!!TODO: error handling infrastructure?? 
+      if (request.status != 200)
+        return;
+
+      var response = request.responseXML.getElementsByTagName("ajax-response");
+      if (response == null || response.length != 1)
+         return;
+      this._processAjaxResponse( response[0].childNodes );
+   },
+
+   _processAjaxResponse: function( xmlResponseElements ) {
+      for ( var i = 0 ; i < xmlResponseElements.length ; i++ ) {
+         var responseElement = xmlResponseElements[i];
+
+         // only process nodes of type element.....
+         if ( responseElement.nodeType != 1 )
+            continue;
+
+         var responseType = responseElement.getAttribute("type");
+         var responseId   = responseElement.getAttribute("id");
+
+         if ( responseType == "object" )
+            this._processAjaxObjectUpdate( this.ajaxObjects[ responseId ], responseElement );
+         else if ( responseType == "element" )
+            this._processAjaxElementUpdate( this.ajaxElements[ responseId ], responseElement );
+         else
+            alert('unrecognized AjaxResponse type : ' + responseType );
+      }
+   },
+
+   _processAjaxObjectUpdate: function( ajaxObject, responseElement ) {
+      ajaxObject.ajaxUpdate( responseElement );
+   },
+
+   _processAjaxElementUpdate: function( ajaxElement, responseElement ) {
+      ajaxElement.innerHTML = RicoUtil.getContentAsString(responseElement);
+   }
+
+}
+
+var ajaxEngine = new Rico.AjaxEngine();
+
+
+//-------------------- ricoColor.js
+Rico.Color = Class.create();
+
+Rico.Color.prototype = {
+
+   initialize: function(red, green, blue) {
+      this.rgb = { r: red, g : green, b : blue };
+   },
+
+   setRed: function(r) {
+      this.rgb.r = r;
+   },
+
+   setGreen: function(g) {
+      this.rgb.g = g;
+   },
+
+   setBlue: function(b) {
+      this.rgb.b = b;
+   },
+
+   setHue: function(h) {
+
+      // get an HSB model, and set the new hue...
+      var hsb = this.asHSB();
+      hsb.h = h;
+
+      // convert back to RGB...
+      this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+   },
+
+   setSaturation: function(s) {
+      // get an HSB model, and set the new hue...
+      var hsb = this.asHSB();
+      hsb.s = s;
+
+      // convert back to RGB and set values...
+      this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+   },
+
+   setBrightness: function(b) {
+      // get an HSB model, and set the new hue...
+      var hsb = this.asHSB();
+      hsb.b = b;
+
+      // convert back to RGB and set values...
+      this.rgb = Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
+   },
+
+   darken: function(percent) {
+      var hsb  = this.asHSB();
+      this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
+   },
+
+   brighten: function(percent) {
+      var hsb  = this.asHSB();
+      this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
+   },
+
+   blend: function(other) {
+      this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
+      this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
+      this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
+   },
+
+   isBright: function() {
+      var hsb = this.asHSB();
+      return this.asHSB().b > 0.5;
+   },
+
+   isDark: function() {
+      return ! this.isBright();
+   },
+
+   asRGB: function() {
+      return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
+   },
+
+   asHex: function() {
+      return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
+   },
+
+   asHSB: function() {
+      return Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
+   },
+
+   toString: function() {
+      return this.asHex();
+   }
+
+};
+
+Rico.Color.createFromHex = function(hexCode) {
+
+   if ( hexCode.indexOf('#') == 0 )
+      hexCode = hexCode.substring(1);
+   var red   = hexCode.substring(0,2);
+   var green = hexCode.substring(2,4);
+   var blue  = hexCode.substring(4,6);
+   return new Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
+}
+
+/**
+ * Factory method for creating a color from the background of
+ * an HTML element.
+ */
+Rico.Color.createColorFromBackground = function(elem) {
+
+   var actualColor = RicoUtil.getElementsComputedStyle($(elem), "backgroundColor", "background-color");
+
+   if ( actualColor == "transparent" && elem.parent )
+      return Rico.Color.createColorFromBackground(elem.parent);
+
+   if ( actualColor == null )
+      return new Rico.Color(255,255,255);
+
+   if ( actualColor.indexOf("rgb(") == 0 ) {
+      var colors = actualColor.substring(4, actualColor.length - 1 );
+      var colorArray = colors.split(",");
+      return new Rico.Color( parseInt( colorArray[0] ),
+                            parseInt( colorArray[1] ),
+                            parseInt( colorArray[2] )  );
+
+   }
+   else if ( actualColor.indexOf("#") == 0 ) {
+      var redPart   = parseInt(actualColor.substring(1,3), 16);
+      var greenPart = parseInt(actualColor.substring(3,5), 16);
+      var bluePart  = parseInt(actualColor.substring(5), 16);
+      return new Rico.Color( redPart, greenPart, bluePart );
+   }
+   else
+      return new Rico.Color(255,255,255);
+}
+
+Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
+
+   var red   = 0;
+	var green = 0;
+	var blue  = 0;
+
+   if (saturation == 0) {
+      red = parseInt(brightness * 255.0 + 0.5);
+	   green = red;
+	   blue = red;
+	}
+	else {
+      var h = (hue - Math.floor(hue)) * 6.0;
+      var f = h - Math.floor(h);
+      var p = brightness * (1.0 - saturation);
+      var q = brightness * (1.0 - saturation * f);
+      var t = brightness * (1.0 - (saturation * (1.0 - f)));
+
+      switch (parseInt(h)) {
+         case 0:
+            red   = (brightness * 255.0 + 0.5);
+            green = (t * 255.0 + 0.5);
+            blue  = (p * 255.0 + 0.5);
+            break;
+         case 1:
+            red   = (q * 255.0 + 0.5);
+            green = (brightness * 255.0 + 0.5);
+            blue  = (p * 255.0 + 0.5);
+            break;
+         case 2:
+            red   = (p * 255.0 + 0.5);
+            green = (brightness * 255.0 + 0.5);
+            blue  = (t * 255.0 + 0.5);
+            break;
+         case 3:
+            red   = (p * 255.0 + 0.5);
+            green = (q * 255.0 + 0.5);
+            blue  = (brightness * 255.0 + 0.5);
+            break;
+         case 4:
+            red   = (t * 255.0 + 0.5);
+            green = (p * 255.0 + 0.5);
+            blue  = (brightness * 255.0 + 0.5);
+            break;
+          case 5:
+            red   = (brightness * 255.0 + 0.5);
+            green = (p * 255.0 + 0.5);
+            blue  = (q * 255.0 + 0.5);
+            break;
+	    }
+	}
+
+   return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
+}
+
+Rico.Color.RGBtoHSB = function(r, g, b) {
+
+   var hue;
+   var saturaton;
+   var brightness;
+
+   var cmax = (r > g) ? r : g;
+   if (b > cmax)
+      cmax = b;
+
+   var cmin = (r < g) ? r : g;
+   if (b < cmin)
+      cmin = b;
+
+   brightness = cmax / 255.0;
+   if (cmax != 0)
+      saturation = (cmax - cmin)/cmax;
+   else
+      saturation = 0;
+
+   if (saturation == 0)
+      hue = 0;
+   else {
+      var redc   = (cmax - r)/(cmax - cmin);
+    	var greenc = (cmax - g)/(cmax - cmin);
+    	var bluec  = (cmax - b)/(cmax - cmin);
+
+    	if (r == cmax)
+    	   hue = bluec - greenc;
+    	else if (g == cmax)
+    	   hue = 2.0 + redc - bluec;
+      else
+    	   hue = 4.0 + greenc - redc;
+
+    	hue = hue / 6.0;
+    	if (hue < 0)
+    	   hue = hue + 1.0;
+   }
+
+   return { h : hue, s : saturation, b : brightness };
+}
+
+
+//-------------------- ricoCorner.js
+
+Rico.Corner = {
+
+   round: function(e, options) {
+      var e = $(e);
+      this._setOptions(options);
+
+      var color = this.options.color;
+      if ( this.options.color == "fromElement" )
+         color = this._background(e);
+
+      var bgColor = this.options.bgColor;
+      if ( this.options.bgColor == "fromParent" )
+         bgColor = this._background(e.offsetParent);
+
+      this._roundCornersImpl(e, color, bgColor);
+   },
+
+   _roundCornersImpl: function(e, color, bgColor) {
+      if(this.options.border)
+         this._renderBorder(e,bgColor);
+      if(this._isTopRounded())
+         this._roundTopCorners(e,color,bgColor);
+      if(this._isBottomRounded())
+         this._roundBottomCorners(e,color,bgColor);
+   },
+
+   _renderBorder: function(el,bgColor) {
+      var borderValue = "1px solid " + this._borderColor(bgColor);
+      var borderL = "border-left: "  + borderValue;
+      var borderR = "border-right: " + borderValue;
+      var style   = "style='" + borderL + ";" + borderR +  "'";
+      el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>"
+   },
+
+   _roundTopCorners: function(el, color, bgColor) {
+      var corner = this._createCorner(bgColor);
+      for(var i=0 ; i < this.options.numSlices ; i++ )
+         corner.appendChild(this._createCornerSlice(color,bgColor,i,"top"));
+      el.style.paddingTop = 0;
+      el.insertBefore(corner,el.firstChild);
+   },
+
+   _roundBottomCorners: function(el, color, bgColor) {
+      var corner = this._createCorner(bgColor);
+      for(var i=(this.options.numSlices-1) ; i >= 0 ; i-- )
+         corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom"));
+      el.style.paddingBottom = 0;
+      el.appendChild(corner);
+   },
+
+   _createCorner: function(bgColor) {
+      var corner = document.createElement("div");
+      corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor);
+      return corner;
+   },
+
+   _createCornerSlice: function(color,bgColor, n, position) {
+      var slice = document.createElement("span");
+
+      var inStyle = slice.style;
+      inStyle.backgroundColor = color;
+      inStyle.display  = "block";
+      inStyle.height   = "1px";
+      inStyle.overflow = "hidden";
+      inStyle.fontSize = "1px";
+
+      var borderColor = this._borderColor(color,bgColor);
+      if ( this.options.border && n == 0 ) {
+         inStyle.borderTopStyle    = "solid";
+         inStyle.borderTopWidth    = "1px";
+         inStyle.borderLeftWidth   = "0px";
+         inStyle.borderRightWidth  = "0px";
+         inStyle.borderBottomWidth = "0px";
+         inStyle.height            = "0px"; // assumes css compliant box model
+         inStyle.borderColor       = borderColor;
+      }
+      else if(borderColor) {
+         inStyle.borderColor = borderColor;
+         inStyle.borderStyle = "solid";
+         inStyle.borderWidth = "0px 1px";
+      }
+
+      if ( !this.options.compact && (n == (this.options.numSlices-1)) )
+         inStyle.height = "2px";
+
+      this._setMargin(slice, n, position);
+      this._setBorder(slice, n, position);
+
+      return slice;
+   },
+
+   _setOptions: function(options) {
+      this.options = {
+         corners : "all",
+         color   : "fromElement",
+         bgColor : "fromParent",
+         blend   : true,
+         border  : false,
+         compact : false
+      }.extend(options || {});
+
+      this.options.numSlices = this.options.compact ? 2 : 4;
+      if ( this._isTransparent() )
+         this.options.blend = false;
+   },
+
+   _whichSideTop: function() {
+      if ( this._hasString(this.options.corners, "all", "top") )
+         return "";
+
+      if ( this.options.corners.indexOf("tl") >= 0 && this.options.corners.indexOf("tr") >= 0 )
+         return "";
+
+      if (this.options.corners.indexOf("tl") >= 0)
+         return "left";
+      else if (this.options.corners.indexOf("tr") >= 0)
+          return "right";
+      return "";
+   },
+
+   _whichSideBottom: function() {
+      if ( this._hasString(this.options.corners, "all", "bottom") )
+         return "";
+
+      if ( this.options.corners.indexOf("bl")>=0 && this.options.corners.indexOf("br")>=0 )
+         return "";
+
+      if(this.options.corners.indexOf("bl") >=0)
+         return "left";
+      else if(this.options.corners.indexOf("br")>=0)
+         return "right";
+      return "";
+   },
+
+   _borderColor : function(color,bgColor) {
+      if ( color == "transparent" )
+         return bgColor;
+      else if ( this.options.border )
+         return this.options.border;
+      else if ( this.options.blend )
+         return this._blend( bgColor, color );
+      else
+         return "";
+   },
+
+
+   _setMargin: function(el, n, corners) {
+      var marginSize = this._marginSize(n);
+      var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
+
+      if ( whichSide == "left" ) {
+         el.style.marginLeft = marginSize + "px"; el.style.marginRight = "0px";
+      }
+      else if ( whichSide == "right" ) {
+         el.style.marginRight = marginSize + "px"; el.style.marginLeft  = "0px";
+      }
+      else {
+         el.style.marginLeft = marginSize + "px"; el.style.marginRight = marginSize + "px";
+      }
+   },
+
+   _setBorder: function(el,n,corners) {
+      var borderSize = this._borderSize(n);
+      var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
+
+      if ( whichSide == "left" ) {
+         el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = "0px";
+      }
+      else if ( whichSide == "right" ) {
+         el.style.borderRightWidth = borderSize + "px"; el.style.borderLeftWidth  = "0px";
+      }
+      else {
+         el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
+      }
+   },
+
+   _marginSize: function(n) {
+      if ( this._isTransparent() )
+         return 0;
+
+      var marginSizes          = [ 5, 3, 2, 1 ];
+      var blendedMarginSizes   = [ 3, 2, 1, 0 ];
+      var compactMarginSizes   = [ 2, 1 ];
+      var smBlendedMarginSizes = [ 1, 0 ];
+
+      if ( this.options.compact && this.options.blend )
+         return smBlendedMarginSizes[n];
+      else if ( this.options.compact )
+         return compactMarginSizes[n];
+      else if ( this.options.blend )
+         return blendedMarginSizes[n];
+      else
+         return marginSizes[n];
+   },
+
+   _borderSize: function(n) {
+      var transparentBorderSizes = [ 5, 3, 2, 1 ];
+      var blendedBorderSizes     = [ 2, 1, 1, 1 ];
+      var compactBorderSizes     = [ 1, 0 ];
+      var actualBorderSizes      = [ 0, 2, 0, 0 ];
+
+      if ( this.options.compact && (this.options.blend || this._isTransparent()) )
+         return 1;
+      else if ( this.options.compact )
+         return compactBorderSizes[n];
+      else if ( this.options.blend )
+         return blendedBorderSizes[n];
+      else if ( this.options.border )
+         return actualBorderSizes[n];
+      else if ( this._isTransparent() )
+         return transparentBorderSizes[n];
+      return 0;
+   },
+
+   _hasString: function(str) { for(var i=1 ; i<arguments.length ; i++) if (str.indexOf(arguments[i]) >= 0) return true; return false; },
+   _blend: function(c1, c2) { var cc1 = Rico.Color.createFromHex(c1); cc1.blend(Rico.Color.createFromHex(c2)); return cc1; },
+   _background: function(el) { try { return Rico.Color.createColorFromBackground(el).asHex(); } catch(err) { return "#ffffff"; } },
+   _isTransparent: function() { return this.options.color == "transparent"; },
+   _isTopRounded: function() { return this._hasString(this.options.corners, "all", "top", "tl", "tr"); },
+   _isBottomRounded: function() { return this._hasString(this.options.corners, "all", "bottom", "bl", "br"); },
+   _hasSingleTextChild: function(el) { return el.childNodes.length == 1 && el.childNodes[0].nodeType == 3; }
+}
+
+
+//-------------------- ricoDragAndDrop.js
+Rico.DragAndDrop = Class.create();
+
+Rico.DragAndDrop.prototype = {
+
+   initialize: function() {
+      this.dropZones                = new Array();
+      this.draggables               = new Array();
+      this.currentDragObjects       = new Array();
+      this.dragElement              = null;
+      this.lastSelectedDraggable    = null;
+      this.currentDragObjectVisible = false;
+      this.interestedInMotionEvents = false;
+   },
+
+   registerDropZone: function(aDropZone) {
+      this.dropZones[ this.dropZones.length ] = aDropZone;
+   },
+
+   deregisterDropZone: function(aDropZone) {
+      var newDropZones = new Array();
+      var j = 0;
+      for ( var i = 0 ; i < this.dropZones.length ; i++ ) {
+         if ( this.dropZones[i] != aDropZone )
+            newDropZones[j++] = this.dropZones[i];
+      }
+
+      this.dropZones = newDropZones;
+   },
+
+   clearDropZones: function() {
+      this.dropZones = new Array();
+   },
+
+   registerDraggable: function( aDraggable ) {
+      this.draggables[ this.draggables.length ] = aDraggable;
+      this._addMouseDownHandler( aDraggable );
+   },
+
+   clearSelection: function() {
+      for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+         this.currentDragObjects[i].deselect();
+      this.currentDragObjects = new Array();
+      this.lastSelectedDraggable = null;
+   },
+
+   hasSelection: function() {
+      return this.currentDragObjects.length > 0;
+   },
+
+   setStartDragFromElement: function( e, mouseDownElement ) {
+      this.origPos = RicoUtil.toDocumentPosition(mouseDownElement);
+      this.startx = e.screenX - this.origPos.x
+      this.starty = e.screenY - this.origPos.y
+      //this.startComponentX = e.layerX ? e.layerX : e.offsetX;
+      //this.startComponentY = e.layerY ? e.layerY : e.offsetY;
+      //this.adjustedForDraggableSize = false;
+
+      this.interestedInMotionEvents = this.hasSelection();
+      this._terminateEvent(e);
+   },
+
+   updateSelection: function( draggable, extendSelection ) {
+      if ( ! extendSelection )
+         this.clearSelection();
+
+      if ( draggable.isSelected() ) {
+         this.currentDragObjects.removeItem(draggable);
+         draggable.deselect();
+         if ( draggable == this.lastSelectedDraggable )
+            this.lastSelectedDraggable = null;
+      }
+      else {
+         this.currentDragObjects[ this.currentDragObjects.length ] = draggable;
+         draggable.select();
+         this.lastSelectedDraggable = draggable;
+      }
+   },
+
+   _mouseDownHandler: function(e) {
+      if ( arguments.length == 0 )
+         e = event;
+
+      // if not button 1 ignore it...
+      var nsEvent = e.which != undefined;
+      if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
+         return;
+
+      var eventTarget      = e.target ? e.target : e.srcElement;
+      var draggableObject  = eventTarget.draggable;
+
+      var candidate = eventTarget;
+      while (draggableObject == null && candidate.parentNode) {
+         candidate = candidate.parentNode;
+         draggableObject = candidate.draggable;
+      }
+   
+      if ( draggableObject == null )
+         return;
+
+      this.updateSelection( draggableObject, e.ctrlKey );
+
+      // clear the drop zones postion cache...
+      if ( this.hasSelection() )
+         for ( var i = 0 ; i < this.dropZones.length ; i++ )
+            this.dropZones[i].clearPositionCache();
+
+      this.setStartDragFromElement( e, draggableObject.getMouseDownHTMLElement() );
+   },
+
+
+   _mouseMoveHandler: function(e) {
+      var nsEvent = e.which != undefined;
+      if ( !this.interestedInMotionEvents ) {
+         this._terminateEvent(e);
+         return;
+      }
+
+      if ( ! this.hasSelection() )
+         return;
+
+      if ( ! this.currentDragObjectVisible )
+         this._startDrag(e);
+
+      if ( !this.activatedDropZones )
+         this._activateRegisteredDropZones();
+
+      //if ( !this.adjustedForDraggableSize )
+      //   this._adjustForDraggableSize(e);
+
+      this._updateDraggableLocation(e);
+      this._updateDropZonesHover(e);
+
+      this._terminateEvent(e);
+   },
+
+   _makeDraggableObjectVisible: function(e)
+   {
+      if ( !this.hasSelection() )
+         return;
+
+      var dragElement;
+      if ( this.currentDragObjects.length > 1 )
+         dragElement = this.currentDragObjects[0].getMultiObjectDragGUI(this.currentDragObjects);
+      else
+         dragElement = this.currentDragObjects[0].getSingleObjectDragGUI();
+
+      // go ahead and absolute position it...
+      if ( RicoUtil.getElementsComputedStyle(dragElement, "position")  != "absolute" )
+         dragElement.style.position = "absolute";
+
+      // need to parent him into the document...
+      if ( dragElement.parentNode == null || dragElement.parentNode.nodeType == 11 )
+         document.body.appendChild(dragElement);
+
+      this.dragElement = dragElement;
+      this._updateDraggableLocation(e);
+
+      this.currentDragObjectVisible = true;
+   },
+
+   /**
+   _adjustForDraggableSize: function(e) {
+      var dragElementWidth  = this.dragElement.offsetWidth;
+      var dragElementHeight = this.dragElement.offsetHeight;
+      if ( this.startComponentX > dragElementWidth )
+         this.startx -= this.startComponentX - dragElementWidth + 2;
+      if ( e.offsetY ) {
+         if ( this.startComponentY > dragElementHeight )
+            this.starty -= this.startComponentY - dragElementHeight + 2;
+      }
+      this.adjustedForDraggableSize = true;
+   },
+   **/
+
+   _updateDraggableLocation: function(e) {
+      var dragObjectStyle = this.dragElement.style;
+      dragObjectStyle.left = (e.screenX - this.startx) + "px"
+      dragObjectStyle.top  = (e.screenY - this.starty) + "px";
+   },
+
+   _updateDropZonesHover: function(e) {
+      var n = this.dropZones.length;
+      for ( var i = 0 ; i < n ; i++ ) {
+         if ( ! this._mousePointInDropZone( e, this.dropZones[i] ) )
+            this.dropZones[i].hideHover();
+      }
+
+      for ( var i = 0 ; i < n ; i++ ) {
+         if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
+            if ( this.dropZones[i].canAccept(this.currentDragObjects) )
+               this.dropZones[i].showHover();
+         }
+      }
+   },
+
+   _startDrag: function(e) {
+      for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+         this.currentDragObjects[i].startDrag();
+
+      this._makeDraggableObjectVisible(e);
+   },
+
+   _mouseUpHandler: function(e) {
+      if ( ! this.hasSelection() )
+         return;
+
+      var nsEvent = e.which != undefined;
+      if ( (nsEvent && e.which != 1) || (!nsEvent && e.button != 1))
+         return;
+
+      this.interestedInMotionEvents = false;
+
+      if ( this.dragElement == null ) {
+         this._terminateEvent(e);
+         return;
+      }
+
+      if ( this._placeDraggableInDropZone(e) )
+         this._completeDropOperation(e);
+      else {
+         this._terminateEvent(e);
+         new Effect.Position( this.dragElement,
+                              this.origPos.x,
+                              this.origPos.y,
+                              200,
+                              20,
+                              { complete : this._doCancelDragProcessing.bind(this) } );
+      }
+   },
+
+   _completeDropOperation: function(e) {
+      if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() ) {
+         if ( this.dragElement.parentNode != null )
+            this.dragElement.parentNode.removeChild(this.dragElement);
+      }
+
+      this._deactivateRegisteredDropZones();
+      this._endDrag();
+      this.clearSelection();
+      this.dragElement = null;
+      this.currentDragObjectVisible = false;
+      this._terminateEvent(e);
+   },
+
+   _doCancelDragProcessing: function() {
+      this._cancelDrag();
+
+      if ( this.dragElement != this.currentDragObjects[0].getMouseDownHTMLElement() ) {
+         if ( this.dragElement.parentNode != null ) {
+            this.dragElement.parentNode.removeChild(this.dragElement);
+         }
+      }
+
+      this._deactivateRegisteredDropZones();
+      this.dragElement = null;
+      this.currentDragObjectVisible = false;
+   },
+
+   _placeDraggableInDropZone: function(e) {
+      var foundDropZone = false;
+      var n = this.dropZones.length;
+      for ( var i = 0 ; i < n ; i++ ) {
+         if ( this._mousePointInDropZone( e, this.dropZones[i] ) ) {
+            if ( this.dropZones[i].canAccept(this.currentDragObjects) ) {
+               this.dropZones[i].hideHover();
+               this.dropZones[i].accept(this.currentDragObjects);
+               foundDropZone = true;
+               break;
+            }
+         }
+      }
+
+      return foundDropZone;
+   },
+
+   _cancelDrag: function() {
+      for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+         this.currentDragObjects[i].cancelDrag();
+   },
+
+   _endDrag: function() {
+      for ( var i = 0 ; i < this.currentDragObjects.length ; i++ )
+         this.currentDragObjects[i].endDrag();
+   },
+
+   _mousePointInDropZone: function( e, dropZone ) {
+
+      var absoluteRect = dropZone.getAbsoluteRect();
+
+      return e.clientX  > absoluteRect.left  &&
+             e.clientX  < absoluteRect.right &&
+             e.clientY  > absoluteRect.top   &&
+             e.clientY  < absoluteRect.bottom;
+   },
+
+   _addMouseDownHandler: function( aDraggable )
+   {
+      var htmlElement = aDraggable.getMouseDownHTMLElement();
+      if ( htmlElement != null ) {
+         htmlElement.draggable = aDraggable;
+         this._addMouseDownEvent( htmlElement );
+      }
+   },
+
+   _activateRegisteredDropZones: function() {
+      var n = this.dropZones.length;
+      for ( var i = 0 ; i < n ; i++ ) {
+         var dropZone = this.dropZones[i];
+         if ( dropZone.canAccept(this.currentDragObjects) )
+            dropZone.activate();
+      }
+
+      this.activatedDropZones = true;
+   },
+
+   _deactivateRegisteredDropZones: function() {
+      var n = this.dropZones.length;
+      for ( var i = 0 ; i < n ; i++ )
+         this.dropZones[i].deactivate();
+      this.activatedDropZones = false;
+   },
+
+   _addMouseDownEvent: function( htmlElement ) {
+      if ( typeof document.implementation != "undefined" &&
+         document.implementation.hasFeature("HTML",   "1.0") &&
+         document.implementation.hasFeature("Events", "2.0") &&
+         document.implementation.hasFeature("CSS",    "2.0") ) {
+         htmlElement.addEventListener("mousedown", this._mouseDownHandler.bindAsEventListener(this), false);
+      }
+      else {
+         htmlElement.attachEvent( "onmousedown", this._mouseDownHandler.bindAsEventListener(this) );
+      }
+   },
+
+   _terminateEvent: function(e) {
+      if ( e.stopPropagation != undefined )
+         e.stopPropagation();
+      else if ( e.cancelBubble != undefined )
+         e.cancelBubble = true;
+
+      if ( e.preventDefault != undefined )
+         e.preventDefault();
+      else
+         e.returnValue = false;
+   },
+
+   initializeEventHandlers: function() {
+      if ( typeof document.implementation != "undefined" &&
+         document.implementation.hasFeature("HTML",   "1.0") &&
+         document.implementation.hasFeature("Events", "2.0") &&
+         document.implementation.hasFeature("CSS",    "2.0") ) {
+         document.addEventListener("mouseup",   this._mouseUpHandler.bindAsEventListener(this),  false);
+         document.addEventListener("mousemove", this._mouseMoveHandler.bindAsEventListener(this), false);
+      }
+      else {
+         document.attachEvent( "onmouseup",   this._mouseUpHandler.bindAsEventListener(this) );
+         document.attachEvent( "onmousemove", this._mouseMoveHandler.bindAsEventListener(this) );
+      }
+   }
+}
+
+//var dndMgr = new Rico.DragAndDrop();
+//dndMgr.initializeEventHandlers();
+
+
+//-------------------- ricoDraggable.js
+Rico.Draggable = Class.create();
+
+Rico.Draggable.prototype = {
+
+   initialize: function( type, htmlElement ) {
+      this.type          = type;
+      this.htmlElement   = $(htmlElement);
+      this.selected      = false;
+   },
+
+   /**
+    *   Returns the HTML element that should have a mouse down event
+    *   added to it in order to initiate a drag operation
+    *
+    **/
+   getMouseDownHTMLElement: function() {
+      return this.htmlElement;
+   },
+
+   select: function() {
+      this.selected = true;
+
+      if ( this.showingSelected )
+         return;
+
+      var htmlElement = this.getMouseDownHTMLElement();
+
+      var color = Rico.Color.createColorFromBackground(htmlElement);
+      color.isBright() ? color.darken(0.033) : color.brighten(0.033);
+
+      this.saveBackground = RicoUtil.getElementsComputedStyle(htmlElement, "backgroundColor", "background-color");
+      htmlElement.style.backgroundColor = color.asHex();
+      this.showingSelected = true;
+   },
+
+   deselect: function() {
+      this.selected = false;
+      if ( !this.showingSelected )
+         return;
+
+      var htmlElement = this.getMouseDownHTMLElement();
+
+      htmlElement.style.backgroundColor = this.saveBackground;
+      this.showingSelected = false;
+   },
+
+   isSelected: function() {
+      return this.selected;
+   },
+
+   startDrag: function() {
+   },
+
+   cancelDrag: function() {
+   },
+
+   endDrag: function() {
+   },
+
+   getSingleObjectDragGUI: function() {
+      return this.htmlElement;
+   },
+
+   getMultiObjectDragGUI: function( draggables ) {
+      return this.htmlElement;
+   },
+
+   getDroppedGUI: function() {
+      return this.htmlElement;
+   },
+
+   toString: function() {
+      return this.type + ":" + this.htmlElement + ":";
+   }
+
+}
+
+
+//-------------------- ricoDropzone.js
+Rico.Dropzone = Class.create();
+
+Rico.Dropzone.prototype = {
+
+   initialize: function( htmlElement ) {
+      this.htmlElement  = $(htmlElement);
+      this.absoluteRect = null;
+   },
+
+   getHTMLElement: function() {
+      return this.htmlElement;
+   },
+
+   clearPositionCache: function() {
+      this.absoluteRect = null;
+   },
+
+   getAbsoluteRect: function() {
+      if ( this.absoluteRect == null ) {
+         var htmlElement = this.getHTMLElement();
+         var pos = RicoUtil.toViewportPosition(htmlElement);
+
+         this.absoluteRect = {
+            top:    pos.y,
+            left:   pos.x,
+            bottom: pos.y + htmlElement.offsetHeight,
+            right:  pos.x + htmlElement.offsetWidth
+         };
+      }
+      return this.absoluteRect;
+   },
+
+   activate: function() {
+      var htmlElement = this.getHTMLElement();
+      if (htmlElement == null  || this.showingActive)
+         return;
+
+      this.showingActive = true;
+      this.saveBackgroundColor = htmlElement.style.backgroundColor;
+
+      var fallbackColor = "#ffea84";
+      var currentColor = Rico.Color.createColorFromBackground(htmlElement);
+      if ( currentColor == null )
+         htmlElement.style.backgroundColor = fallbackColor;
+      else {
+         currentColor.isBright() ? currentColor.darken(0.2) : currentColor.brighten(0.2);
+         htmlElement.style.backgroundColor = currentColor.asHex();
+      }
+   },
+
+   deactivate: function() {
+      var htmlElement = this.getHTMLElement();
+      if (htmlElement == null || !this.showingActive)
+         return;
+
+      htmlElement.style.backgroundColor = this.saveBackgroundColor;
+      this.showingActive = false;
+      this.saveBackgroundColor = null;
+   },
+
+   showHover: function() {
+      var htmlElement = this.getHTMLElement();
+      if ( htmlElement == null || this.showingHover )
+         return;
+
+      this.saveBorderWidth = htmlElement.style.borderWidth;
+      this.saveBorderStyle = htmlElement.style.borderStyle;
+      this.saveBorderColor = htmlElement.style.borderColor;
+
+      this.showingHover = true;
+      htmlElement.style.borderWidth = "1px";
+      htmlElement.style.borderStyle = "solid";
+      //htmlElement.style.borderColor = "#ff9900";
+      htmlElement.style.borderColor = "#ffff00";
+   },
+
+   hideHover: function() {
+      var htmlElement = this.getHTMLElement();
+      if ( htmlElement == null || !this.showingHover )
+         return;
+
+      htmlElement.style.borderWidth = this.saveBorderWidth;
+      htmlElement.style.borderStyle = this.saveBorderStyle;
+      htmlElement.style.borderColor = this.saveBorderColor;
+      this.showingHover = false;
+   },
+
+   canAccept: function(draggableObjects) {
+      return true;
+   },
+
+   accept: function(draggableObjects) {
+      var htmlElement = this.getHTMLElement();
+      if ( htmlElement == null )
+         return;
+
+      n = draggableObjects.length;
+      for ( var i = 0 ; i < n ; i++ )
+      {
+         var theGUI = draggableObjects[i].getDroppedGUI();
+         if ( RicoUtil.getElementsComputedStyle( theGUI, "position" ) == "absolute" )
+         {
+            theGUI.style.position = "static";
+            theGUI.style.top = "";
+            theGUI.style.top = "";
+         }
+         htmlElement.appendChild(theGUI);
+      }
+   }
+}
+
+
+//-------------------- ricoEffects.js
+
+/**
+  *  Use the Effect namespace for effects.  If using scriptaculous effects
+  *  this will already be defined, otherwise we'll just create an empty
+  *  object for it...
+ **/
+if ( window.Effect == undefined )
+   Effect = {};
+
+Effect.SizeAndPosition = Class.create();
+Effect.SizeAndPosition.prototype = {
+
+   initialize: function(element, x, y, w, h, duration, steps, options) {
+      this.element = $(element);
+      this.x = x;
+      this.y = y;
+      this.w = w;
+      this.h = h;
+      this.duration = duration;
+      this.steps    = steps;
+      this.options  = arguments[7] || {};
+
+      this.sizeAndPosition();
+   },
+
+   sizeAndPosition: function() {
+      if (this.isFinished()) {
+         if(this.options.complete) this.options.complete(this);
+         return;
+      }
+
+      if (this.timer)
+         clearTimeout(this.timer);
+
+      var stepDuration = Math.round(this.duration/this.steps) ;
+
+      // Get original values: x,y = top left corner;  w,h = width height
+      var currentX = this.element.offsetLeft;
+      var currentY = this.element.offsetTop;
+      var currentW = this.element.offsetWidth;
+      var currentH = this.element.offsetHeight;
+
+      // If values not set, or zero, we do not modify them, and take original as final as well
+      this.x = (this.x) ? this.x : currentX;
+      this.y = (this.y) ? this.y : currentY;
+      this.w = (this.w) ? this.w : currentW;
+      this.h = (this.h) ? this.h : currentH;
+
+      // how much do we need to modify our values for each step?
+      var difX = this.steps >  0 ? (this.x - currentX)/this.steps : 0;
+      var difY = this.steps >  0 ? (this.y - currentY)/this.steps : 0;
+      var difW = this.steps >  0 ? (this.w - currentW)/this.steps : 0;
+      var difH = this.steps >  0 ? (this.h - currentH)/this.steps : 0;
+
+      this.moveBy(difX, difY);
+      this.resizeBy(difW, difH);
+
+      this.duration -= stepDuration;
+      this.steps--;
+
+      this.timer = setTimeout(this.sizeAndPosition.bind(this), stepDuration);
+   },
+
+   isFinished: function() {
+      return this.steps <= 0;
+   },
+
+   moveBy: function( difX, difY ) {
+      var currentLeft = this.element.offsetLeft;
+      var currentTop  = this.element.offsetTop;
+      var intDifX     = parseInt(difX);
+      var intDifY     = parseInt(difY);
+
+      var style = this.element.style;
+      if ( intDifX != 0 )
+         style.left = (currentLeft + intDifX) + "px";
+      if ( intDifY != 0 )
+         style.top  = (currentTop + intDifY) + "px";
+   },
+
+   resizeBy: function( difW, difH ) {
+      var currentWidth  = this.element.offsetWidth;
+      var currentHeight = this.element.offsetHeight;
+      var intDifW       = parseInt(difW);
+      var intDifH       = parseInt(difH);
+
+      var style = this.element.style;
+      if ( intDifW != 0 )
+         style.width   = (currentWidth  + intDifW) + "px";
+      if ( intDifH != 0 )
+         style.height  = (currentHeight + intDifH) + "px";
+   }
+}
+
+Effect.Size = Class.create();
+Effect.Size.prototype = {
+
+   initialize: function(element, w, h, duration, steps, options) {
+      new Effect.SizeAndPosition(element, null, null, w, h, duration, steps, options);
+  }
+}
+
+Effect.Position = Class.create();
+Effect.Position.prototype = {
+
+   initialize: function(element, x, y, duration, steps, options) {
+      new Effect.SizeAndPosition(element, x, y, null, null, duration, steps, options);
+  }
+}
+
+Effect.Round = Class.create();
+Effect.Round.prototype = {
+
+   initialize: function(tagName, className, options) {
+      var elements = document.getElementsByTagAndClassName(tagName,className);
+      for ( var i = 0 ; i < elements.length ; i++ )
+         Rico.Corner.round( elements[i], options );
+   }
+};
+
+Effect.FadeTo = Class.create();
+Effect.FadeTo.prototype = {
+
+   initialize: function( element, opacity, duration, steps, options) {
+      this.element  = $(element);
+      this.opacity  = opacity;
+      this.duration = duration;
+      this.steps    = steps;
+      this.options  = arguments[4] || {};
+      this.fadeTo();
+   },
+
+   fadeTo: function() {
+      if (this.isFinished()) {
+         if(this.options.complete) this.options.complete(this);
+         return;
+      }
+
+      if (this.timer)
+         clearTimeout(this.timer);
+
+      var stepDuration = Math.round(this.duration/this.steps) ;
+      var currentOpacity = this.getElementOpacity();
+      var delta = this.steps > 0 ? (this.opacity - currentOpacity)/this.steps : 0;
+
+      this.changeOpacityBy(delta);
+      this.duration -= stepDuration;
+      this.steps--;
+
+      this.timer = setTimeout(this.fadeTo.bind(this), stepDuration);
+   },
+
+   changeOpacityBy: function(v) {
+      var currentOpacity = this.getElementOpacity();
+      var newOpacity = Math.max(0, Math.min(currentOpacity+v, 1));
+      this.element.ricoOpacity = newOpacity;
+
+      this.element.style.filter = "alpha(opacity:"+Math.round(newOpacity*100)+")";
+      this.element.style.opacity = newOpacity; /*//*/;
+   },
+
+   isFinished: function() {
+      return this.steps <= 0;
+   },
+
+   getElementOpacity: function() {
+      if ( this.element.ricoOpacity == undefined ) {
+         var opacity;
+         if ( this.element.currentStyle ) {
+            opacity = this.element.currentStyle.opacity;
+         }
+         else if ( document.defaultView.getComputedStyle != undefined ) {
+            var computedStyle = document.defaultView.getComputedStyle;
+            opacity = computedStyle(this.element, null).getPropertyValue('opacity');
+         }
+
+         this.element.ricoOpacity = opacity != undefined ? opacity : 1.0;
+      }
+
+      return parseFloat(this.element.ricoOpacity);
+   }
+}
+
+Effect.AccordionSize = Class.create();
+
+Effect.AccordionSize.prototype = {
+
+   initialize: function(e1, e2, start, end, duration, steps, options) {
+      this.e1       = $(e1);
+      this.e2       = $(e2);
+      this.start    = start;
+      this.end      = end;
+      this.duration = duration;
+      this.steps    = steps;
+      this.options  = arguments[6] || {};
+
+      this.accordionSize();
+   },
+
+   accordionSize: function() {
+
+      if (this.isFinished()) {
+         // just in case there are round errors or such...
+         this.e1.style.height = this.start + "px";
+         this.e2.style.height = this.end + "px";
+
+         if(this.options.complete)
+            this.options.complete(this);
+         return;
+      }
+
+      if (this.timer)
+         clearTimeout(this.timer);
+
+      var stepDuration = Math.round(this.duration/this.steps) ;
+
+      var diff = this.steps > 0 ? (parseInt(this.e1.offsetHeight) - this.start)/this.steps : 0;
+      this.resizeBy(diff);
+
+      this.duration -= stepDuration;
+      this.steps--;
+
+      this.timer = setTimeout(this.accordionSize.bind(this), stepDuration);
+   },
+
+   isFinished: function() {
+      return this.steps <= 0;
+   },
+
+   resizeBy: function(diff) {
+      var h1Height = this.e1.offsetHeight;
+      var h2Height = this.e2.offsetHeight;
+      var intDiff = parseInt(diff);
+      if ( diff != 0 ) {
+         this.e1.style.height = (h1Height - intDiff) + "px";
+         this.e2.style.height = (h2Height + intDiff) + "px";
+      }
+   }
+
+};
+
+
+//-------------------- ricoLiveGrid.js
+
+// Rico.LiveGridMetaData -----------------------------------------------------
+
+Rico.LiveGridMetaData = Class.create();
+
+Rico.LiveGridMetaData.prototype = {
+
+   initialize: function( pageSize, totalRows, columnCount, options ) {
+      this.pageSize  = pageSize;
+      this.totalRows = totalRows;
+      this.setOptions(options);
+      this.scrollArrowHeight = 16;
+      this.columnCount = columnCount;
+   },
+
+   setOptions: function(options) {
+      this.options = {
+         largeBufferSize    : 7.0,   // 7 pages
+         nearLimitFactor    : 0.2    // 20% of buffer
+      }.extend(options || {});
+   },
+
+   getPageSize: function() {
+      return this.pageSize;
+   },
+
+   getTotalRows: function() {
+      return this.totalRows;
+   },
+
+   setTotalRows: function(n) {
+      this.totalRows = n;
+   },
+
+   getLargeBufferSize: function() {
+      return parseInt(this.options.largeBufferSize * this.pageSize);
+   },
+
+   getLimitTolerance: function() {
+      return parseInt(this.getLargeBufferSize() * this.options.nearLimitFactor);
+   }
+};
+
+// Rico.LiveGridScroller -----------------------------------------------------
+
+Rico.LiveGridScroller = Class.create();
+
+Rico.LiveGridScroller.prototype = {
+
+   initialize: function(liveGrid, viewPort) {
+      this.isIE = navigator.userAgent.toLowerCase().indexOf("msie") >= 0;
+      this.liveGrid = liveGrid;
+      this.metaData = liveGrid.metaData;
+      this.createScrollBar();
+      this.scrollTimeout = null;
+      this.lastScrollPos = 0;
+      this.viewPort = viewPort;
+      this.rows = new Array();
+   },
+
+   isUnPlugged: function() {
+      return this.scrollerDiv.onscroll == null;
+   },
+
+   plugin: function() {
+      this.scrollerDiv.onscroll = this.handleScroll.bindAsEventListener(this);
+   },
+
+   unplug: function() {
+      this.scrollerDiv.onscroll = null;
+   },
+
+   sizeIEHeaderHack: function() {
+      if ( !this.isIE ) return;
+      var headerTable = $(this.liveGrid.tableId + "_header");
+      if ( headerTable )
+         headerTable.rows[0].cells[0].style.width =
+            (headerTable.rows[0].cells[0].offsetWidth + 1) + "px";
+   },
+
+   createScrollBar: function() {
+      var visibleHeight = this.liveGrid.viewPort.visibleHeight();
+      // create the outer div...
+      this.scrollerDiv  = document.createElement("div");
+      var scrollerStyle = this.scrollerDiv.style;
+      scrollerStyle.borderRight = "1px solid #ababab"; // hard coded color!!!
+      scrollerStyle.position    = "relative";
+      scrollerStyle.left        = this.isIE ? "-6px" : "-3px";
+      scrollerStyle.width       = "19px";
+      scrollerStyle.height      = visibleHeight + "px";
+      scrollerStyle.overflow    = "auto";
+
+      // create the inner div...
+      this.heightDiv = document.createElement("div");
+      this.heightDiv.style.width  = "1px";
+
+      this.heightDiv.style.height = parseInt(visibleHeight *
+                        this.metaData.getTotalRows()/this.metaData.getPageSize()) + "px" ;
+      this.scrollerDiv.appendChild(this.heightDiv);
+      this.scrollerDiv.onscroll = this.handleScroll.bindAsEventListener(this);
+
+     var table = this.liveGrid.table;
+     table.parentNode.parentNode.insertBefore( this.scrollerDiv, table.parentNode.nextSibling );
+   },
+
+   updateSize: function() {
+      var table = this.liveGrid.table;
+      var visibleHeight = this.viewPort.visibleHeight();
+      this.heightDiv.style.height = parseInt(visibleHeight *
+                                  this.metaData.getTotalRows()/this.metaData.getPageSize()) + "px";
+   },
+
+   rowToPixel: function(rowOffset) {
+      return (rowOffset / this.metaData.getTotalRows()) * this.heightDiv.offsetHeight
+   },
+   
+   moveScroll: function(rowOffset) {
+      this.scrollerDiv.scrollTop = this.rowToPixel(rowOffset);
+      if ( this.metaData.options.onscroll )
+         this.metaData.options.onscroll( this.liveGrid, rowOffset );    
+   },
+
+   handleScroll: function() {
+     if ( this.scrollTimeout )
+         clearTimeout( this.scrollTimeout );
+
+      var contentOffset = parseInt(this.scrollerDiv.scrollTop / this.viewPort.rowHeight);
+      this.liveGrid.requestContentRefresh(contentOffset);
+      this.viewPort.scrollTo(this.scrollerDiv.scrollTop);
+      
+      if ( this.metaData.options.onscroll )
+         this.metaData.options.onscroll( this.liveGrid, contentOffset );
+
+      this.scrollTimeout = setTimeout( this.scrollIdle.bind(this), 1200 );
+   },
+
+   scrollIdle: function() {
+      if ( this.metaData.options.onscrollidle )
+         this.metaData.options.onscrollidle();
+   }
+};
+
+// Rico.LiveGridBuffer -----------------------------------------------------
+
+Rico.LiveGridBuffer = Class.create();
+
+Rico.LiveGridBuffer.prototype = {
+
+   initialize: function(metaData, viewPort) {
+      this.startPos = 0;
+      this.size     = 0;
+      this.metaData = metaData;
+      this.rows     = new Array();
+      this.updateInProgress = false;
+      this.viewPort = viewPort;
+      this.maxBufferSize = metaData.getLargeBufferSize() * 2;
+      this.maxFetchSize = metaData.getLargeBufferSize();
+      this.lastOffset = 0;
+   },
+
+   getBlankRow: function() {
+      if (!this.blankRow ) {
+         this.blankRow = new Array();
+         for ( var i=0; i < this.metaData.columnCount ; i++ ) 
+            this.blankRow[i] = "&nbsp;";
+     }
+     return this.blankRow;
+   },
+   
+   loadRows: function(ajaxResponse) {
+      var rowsElement = ajaxResponse.getElementsByTagName('rows')[0];
+      this.updateUI = rowsElement.getAttribute("update_ui") == "true"
+      var newRows = new Array()
+      var trs = rowsElement.getElementsByTagName("tr");
+      for ( var i=0 ; i < trs.length; i++ ) {
+         var row = newRows[i] = new Array(); 
+         var cells = trs[i].getElementsByTagName("td");
+         for ( var j=0; j < cells.length ; j++ ) {
+            var cell = cells[j];
+            var convertSpaces = cell.getAttribute("convert_spaces") == "true";
+            var cellContent = RicoUtil.getContentAsString(cell);
+            row[j] = convertSpaces ? this.convertSpaces(cellContent) : cellContent;
+            if (!row[j]) 
+               row[j] = '&nbsp;';
+         }
+      }
+      return newRows;
+   },
+      
+   update: function(ajaxResponse, start) {
+     var newRows = this.loadRows(ajaxResponse);
+      if (this.rows.length == 0) { // initial load
+         this.rows = newRows;
+         this.size = this.rows.length;
+         this.startPos = start;
+         return;
+      }
+      if (start > this.startPos) { //appending
+         if (this.startPos + this.rows.length < start) {
+            this.rows =  newRows;
+            this.startPos = start;//
+         } else {
+              this.rows = this.rows.concat( newRows.slice(0, newRows.length));
+            if (this.rows.length > this.maxBufferSize) {
+               var fullSize = this.rows.length;
+               this.rows = this.rows.slice(this.rows.length - this.maxBufferSize, this.rows.length)
+               this.startPos = this.startPos +  (fullSize - this.rows.length);
+            }
+         }
+      } else { //prepending
+         if (start + newRows.length < this.startPos) {
+            this.rows =  newRows;
+         } else {
+            this.rows = newRows.slice(0, this.startPos).concat(this.rows);
+            if (this.rows.length > this.maxBufferSize) 
+               this.rows = this.rows.slice(0, this.maxBufferSize)
+         }
+         this.startPos =  start;
+      }
+      this.size = this.rows.length;
+   },
+   
+   clear: function() {
+      this.rows = new Array();
+      this.startPos = 0;
+      this.size = 0;
+   },
+
+   isOverlapping: function(start, size) {
+      return ((start < this.endPos()) && (this.startPos < start + size)) || (this.endPos() == 0)
+   },
+
+   isInRange: function(position) {
+      return (position >= this.startPos) && (position + this.metaData.getPageSize() <= this.endPos()); 
+             //&& this.size()  != 0;
+   },
+
+   isNearingTopLimit: function(position) {
+      return position - this.startPos < this.metaData.getLimitTolerance();
+   },
+
+   endPos: function() {
+      return this.startPos + this.rows.length;
+   },
+   
+   isNearingBottomLimit: function(position) {
+      return this.endPos() - (position + this.metaData.getPageSize()) < this.metaData.getLimitTolerance();
+   },
+
+   isAtTop: function() {
+      return this.startPos == 0;
+   },
+
+   isAtBottom: function() {
+      return this.endPos() == this.metaData.getTotalRows();
+   },
+
+   isNearingLimit: function(position) {
+      return ( !this.isAtTop()    && this.isNearingTopLimit(position)) ||
+             ( !this.isAtBottom() && this.isNearingBottomLimit(position) )
+   },
+
+   getFetchSize: function(offset) {
+      var adjustedOffset = this.getFetchOffset(offset);
+      var adjustedSize = 0;
+      if (adjustedOffset >= this.startPos) { //apending
+         var endFetchOffset = this.maxFetchSize  + adjustedOffset;
+         if (endFetchOffset > this.metaData.totalRows)
+            endFetchOffset = this.metaData.totalRows;
+         adjustedSize = endFetchOffset - adjustedOffset;   
+      } else {//prepending
+         var adjustedSize = this.startPos - adjustedOffset;
+         if (adjustedSize > this.maxFetchSize)
+            adjustedSize = this.maxFetchSize;
+      }
+      return adjustedSize;
+   }, 
+
+   getFetchOffset: function(offset) {
+      var adjustedOffset = offset;
+      if (offset > this.startPos)  //apending
+         adjustedOffset = (offset > this.endPos()) ? offset :  this.endPos(); 
+      else { //prepending
+         if (offset + this.maxFetchSize >= this.startPos) {
+            var adjustedOffset = this.startPos - this.maxFetchSize;
+            if (adjustedOffset < 0)
+               adjustedOffset = 0;
+         }
+      }
+      this.lastOffset = adjustedOffset;
+      return adjustedOffset;
+   },
+
+   getRows: function(start, count) {
+      var begPos = start - this.startPos
+      var endPos = begPos + count
+
+      // er? need more data...
+      if ( endPos > this.size )
+         endPos = this.size
+
+      var results = new Array()
+      var index = 0;
+      for ( var i=begPos ; i < endPos; i++ ) {
+         results[index++] = this.rows[i]
+      }
+      return results
+   },
+
+   convertSpaces: function(s) {
+      return s.split(" ").join("&nbsp;");
+   }
+
+};
+
+
+//Rico.GridViewPort --------------------------------------------------
+Rico.GridViewPort = Class.create();
+
+Rico.GridViewPort.prototype = {
+
+   initialize: function(table, rowHeight, visibleRows, buffer, liveGrid) {
+      this.lastDisplayedStartPos = 0;
+      this.div = table.parentNode;
+      this.table = table
+      this.rowHeight = rowHeight;
+      this.div.style.height = this.rowHeight * visibleRows;
+      this.div.style.overflow = "hidden";
+      this.buffer = buffer;
+      this.liveGrid = liveGrid;
+      this.visibleRows = visibleRows + 1;
+      this.lastPixelOffset = 0;
+      this.startPos = 0;
+   },
+
+   populateRow: function(htmlRow, row) {
+      for (var j=0; j < row.length; j++) {
+         htmlRow.cells[j].innerHTML = row[j]
+      }
+   },
+   
+   bufferChanged: function() {
+      this.refreshContents( parseInt(this.lastPixelOffset / this.rowHeight));
+   },
+   
+   clearRows: function() {
+      if (!this.isBlank) {
+         for (var i=0; i < this.visibleRows; i++)
+            this.populateRow(this.table.rows[i], this.buffer.getBlankRow());
+         this.isBlank = true;
+      }
+   },
+   
+   clearContents: function() {   
+      this.clearRows();
+      this.scrollTo(0);
+      this.startPos = 0;
+      this.lastStartPos = -1;   
+   },
+   
+   refreshContents: function(startPos) {
+      if (startPos == this.lastRowPos && !this.isPartialBlank && !this.isBlank) {
+         return;
+      }
+      if ((startPos + this.visibleRows < this.buffer.startPos)  
+          || (this.buffer.startPos + this.buffer.size < startPos) 
+          || (this.buffer.size == 0)) {
+         this.clearRows();
+         return;
+      }
+      this.isBlank = false;
+      var viewPrecedesBuffer = this.buffer.startPos > startPos
+      var contentStartPos = viewPrecedesBuffer ? this.buffer.startPos: startPos;
+   
+      var contentEndPos = (this.buffer.startPos + this.buffer.size < startPos + this.visibleRows) 
+                                 ? this.buffer.startPos + this.buffer.size
+                                 : startPos + this.visibleRows;       
+      var rowSize = contentEndPos - contentStartPos;
+      var rows = this.buffer.getRows(contentStartPos, rowSize ); 
+      var blankSize = this.visibleRows - rowSize;
+      var blankOffset = viewPrecedesBuffer ? 0: rowSize;
+      var contentOffset = viewPrecedesBuffer ? blankSize: 0;
+
+      for (var i=0; i < rows.length; i++) {//initialize what we have
+        this.populateRow(this.table.rows[i + contentOffset], rows[i]);
+      }       
+      for (var i=0; i < blankSize; i++) {// blank out the rest 
+        this.populateRow(this.table.rows[i + blankOffset], this.buffer.getBlankRow());
+      }
+      this.isPartialBlank = blankSize > 0;
+      this.lastRowPos = startPos;   
+   },
+
+   scrollTo: function(pixelOffset) {      
+      if (this.lastPixelOffset == pixelOffset)
+         return;
+
+      this.refreshContents(parseInt(pixelOffset / this.rowHeight))
+      this.div.scrollTop = pixelOffset % this.rowHeight        
+      
+      this.lastPixelOffset = pixelOffset;
+   },
+   
+   visibleHeight: function() {
+      return parseInt(this.div.style.height);
+   }
+   
+};
+
+
+Rico.LiveGridRequest = Class.create();
+Rico.LiveGridRequest.prototype = {
+   initialize: function( requestOffset, options ) {
+      this.requestOffset = requestOffset;
+   }
+};
+
+// Rico.LiveGrid -----------------------------------------------------
+
+Rico.LiveGrid = Class.create();
+
+Rico.LiveGrid.prototype = {
+
+   initialize: function( tableId, visibleRows, totalRows, url, options ) {
+      if ( options == null )
+         options = {};
+
+      this.tableId     = tableId; 
+      this.table       = $(tableId);
+      var columnCount  = this.table.rows[0].cells.length
+      this.metaData    = new Rico.LiveGridMetaData(visibleRows, totalRows, columnCount, options);
+      this.buffer      = new Rico.LiveGridBuffer(this.metaData);
+
+      var rowCount = this.table.rows.length;
+      this.viewPort =  new Rico.GridViewPort(this.table, 
+                                            this.table.offsetHeight/rowCount,
+                                            visibleRows,
+                                            this.buffer, this);
+      this.scroller    = new Rico.LiveGridScroller(this,this.viewPort);
+      
+      this.additionalParms       = options.requestParameters || [];
+      
+      options.sortHandler = this.sortHandler.bind(this);
+
+      if ( $(tableId + '_header') )
+         this.sort = new Rico.LiveGridSort(tableId + '_header', options)
+
+      this.processingRequest = null;
+      this.unprocessedRequest = null;
+
+      this.initAjax(url);
+      if ( options.prefetchBuffer || options.prefetchOffset > 0) {
+         var offset = 0;
+         if (options.offset ) {
+            offset = options.offset;            
+            this.scroller.moveScroll(offset);
+            this.viewPort.scrollTo(this.scroller.rowToPixel(offset));            
+         }
+         if (options.sortCol) {
+             this.sortCol = options.sortCol;
+             this.sortDir = options.sortDir;
+         }
+         this.requestContentRefresh(offset);
+      }
+   },
+
+   resetContents: function() {
+      this.scroller.moveScroll(0);
+      this.buffer.clear();
+      this.viewPort.clearContents();
+   },
+   
+   sortHandler: function(column) {
+      this.sortCol = column.name;
+      this.sortDir = column.currentSort;
+
+      this.resetContents();
+      this.requestContentRefresh(0) 
+   },
+   
+   setRequestParams: function() {
+      this.additionalParms = [];
+      for ( var i=0 ; i < arguments.length ; i++ )
+         this.additionalParms[i] = arguments[i];
+   },
+
+   setTotalRows: function( newTotalRows ) {
+      this.resetContents();
+      this.metaData.setTotalRows(newTotalRows);
+      this.scroller.updateSize();
+   },
+
+   initAjax: function(url) {
+      ajaxEngine.registerRequest( this.tableId + '_request', url );
+      ajaxEngine.registerAjaxObject( this.tableId + '_updater', this );
+   },
+
+   invokeAjax: function() {
+   },
+
+   handleTimedOut: function() {
+      //server did not respond in 4 seconds... assume that there could have been
+      //an error or something, and allow requests to be processed again...
+      this.processingRequest = null;
+      this.processQueuedRequest();
+   },
+
+   fetchBuffer: function(offset) {
+      if ( this.buffer.isInRange(offset) &&
+         !this.buffer.isNearingLimit(offset)) {
+         return;
+      }
+      if (this.processingRequest) {
+          this.unprocessedRequest = new Rico.LiveGridRequest(offset);
+         return;
+      }
+      var bufferStartPos = this.buffer.getFetchOffset(offset);
+      this.processingRequest = new Rico.LiveGridRequest(offset);
+      this.processingRequest.bufferOffset = bufferStartPos;   
+      var fetchSize = this.buffer.getFetchSize(offset);
+      var partialLoaded = false;
+      var callParms = []; 
+      callParms.push(this.tableId + '_request');
+      callParms.push('id='        + this.tableId);
+      callParms.push('page_size=' + fetchSize);
+      callParms.push('offset='    + bufferStartPos);
+      if ( this.sortCol) {
+         callParms.push('sort_col='    + this.sortCol);
+         callParms.push('sort_dir='    + this.sortDir);
+      }
+      
+      for( var i=0 ; i < this.additionalParms.length ; i++ )
+         callParms.push(this.additionalParms[i]);
+      ajaxEngine.sendRequest.apply( ajaxEngine, callParms );
+        
+      this.timeoutHandler = setTimeout( this.handleTimedOut.bind(this), 20000 ); //todo: make as option
+   },
+
+   requestContentRefresh: function(contentOffset) {
+      this.fetchBuffer(contentOffset);
+   },
+
+   ajaxUpdate: function(ajaxResponse) {
+      try {
+         clearTimeout( this.timeoutHandler );
+         this.buffer.update(ajaxResponse,this.processingRequest.bufferOffset);
+         this.viewPort.bufferChanged();
+      }
+      catch(err) {}
+      finally {this.processingRequest = null; }
+      this.processQueuedRequest();
+   },
+
+   processQueuedRequest: function() {
+      if (this.unprocessedRequest != null) {
+         this.requestContentRefresh(this.unprocessedRequest.requestOffset);
+         this.unprocessedRequest = null
+      }  
+   }
+ 
+};
+
+
+//-------------------- ricoLiveGridSort.js
+Rico.LiveGridSort = Class.create();
+
+Rico.LiveGridSort.prototype = {
+
+   initialize: function(headerTableId, options) {
+      this.headerTableId = headerTableId;
+      this.headerTable   = $(headerTableId);
+      this.setOptions(options);
+      this.applySortBehavior();
+
+      if ( this.options.sortCol ) {
+         this.setSortUI( this.options.sortCol, this.options.sortDir );
+      }
+   },
+
+   setSortUI: function( columnName, sortDirection ) {
+      var cols = this.options.columns;
+      for ( var i = 0 ; i < cols.length ; i++ ) {
+         if ( cols[i].name == columnName ) {
+            this.setColumnSort(i, sortDirection);
+            break;
+         }
+      }
+   },
+
+   setOptions: function(options) {
+      this.options = {
+         sortAscendImg:    'images/sort_asc.gif',
+         sortDescendImg:   'images/sort_desc.gif',
+         imageWidth:       9,
+         imageHeight:      5,
+         ajaxSortURLParms: []
+      }.extend(options);
+
+      // preload the images...
+      new Image().src = this.options.sortAscendImg;
+      new Image().src = this.options.sortDescendImg;
+
+      this.sort = options.sortHandler;
+      if ( !this.options.columns )
+         this.options.columns = this.introspectForColumnInfo();
+      else {
+         // allow client to pass { columns: [ ["a", true], ["b", false] ] }
+         // and convert to an array of Rico.TableColumn objs...
+         this.options.columns = this.convertToTableColumns(this.options.columns);
+      }
+   },
+
+   applySortBehavior: function() {
+      var headerRow   = this.headerTable.rows[0];
+      var headerCells = headerRow.cells;
+      for ( var i = 0 ; i < headerCells.length ; i++ ) {
+         this.addSortBehaviorToColumn( i, headerCells[i] );
+      }
+   },
+
+   addSortBehaviorToColumn: function( n, cell ) {
+      if ( this.options.columns[n].isSortable() ) {
+         cell.id            = this.headerTableId + '_' + n;
+         cell.style.cursor  = 'pointer';
+         cell.onclick       = this.headerCellClicked.bindAsEventListener(this);
+         cell.innerHTML     = cell.innerHTML + '<span id="' + this.headerTableId + '_img_' + n + '">'
+                           + '&nbsp;&nbsp;&nbsp;</span>';
+      }
+   },
+
+   // event handler....
+   headerCellClicked: function(evt) {
+      var eventTarget = evt.target ? evt.target : evt.srcElement;
+      var cellId = eventTarget.id;
+      var columnNumber = parseInt(cellId.substring( cellId.lastIndexOf('_') + 1 ));
+      var sortedColumnIndex = this.getSortedColumnIndex();
+      if ( sortedColumnIndex != -1 ) {
+         if ( sortedColumnIndex != columnNumber ) {
+            this.removeColumnSort(sortedColumnIndex);
+            this.setColumnSort(columnNumber, Rico.TableColumn.SORT_ASC);
+         }
+         else
+            this.toggleColumnSort(sortedColumnIndex);
+      }
+      else
+         this.setColumnSort(columnNumber, Rico.TableColumn.SORT_ASC);
+
+      if (this.options.sortHandler) {
+         this.options.sortHandler(this.options.columns[columnNumber]);
+      }
+   },
+
+   removeColumnSort: function(n) {
+      this.options.columns[n].setUnsorted();
+      this.setSortImage(n);
+   },
+
+   setColumnSort: function(n, direction) {
+      this.options.columns[n].setSorted(direction);
+      this.setSortImage(n);
+   },
+
+   toggleColumnSort: function(n) {
+      this.options.columns[n].toggleSort();
+      this.setSortImage(n);
+   },
+
+   setSortImage: function(n) {
+      var sortDirection = this.options.columns[n].getSortDirection();
+
+      var sortImageSpan = $( this.headerTableId + '_img_' + n );
+      if ( sortDirection == Rico.TableColumn.UNSORTED )
+         sortImageSpan.innerHTML = '&nbsp;&nbsp;';
+      else if ( sortDirection == Rico.TableColumn.SORT_ASC )
+         sortImageSpan.innerHTML = '&nbsp;&nbsp;<img width="'  + this.options.imageWidth    + '" ' +
+                                                     'height="'+ this.options.imageHeight   + '" ' +
+                                                     'src="'   + this.options.sortAscendImg + '"/>';
+      else if ( sortDirection == Rico.TableColumn.SORT_DESC )
+         sortImageSpan.innerHTML = '&nbsp;&nbsp;<img width="'  + this.options.imageWidth    + '" ' +
+                                                     'height="'+ this.options.imageHeight   + '" ' +
+                                                     'src="'   + this.options.sortDescendImg + '"/>';
+   },
+
+   getSortedColumnIndex: function() {
+      var cols = this.options.columns;
+      for ( var i = 0 ; i < cols.length ; i++ ) {
+         if ( cols[i].isSorted() )
+            return i;
+      }
+
+      return -1;
+   },
+
+   introspectForColumnInfo: function() {
+      var columns = new Array();
+      var headerRow   = this.headerTable.rows[0];
+      var headerCells = headerRow.cells;
+      for ( var i = 0 ; i < headerCells.length ; i++ )
+         columns.push( new Rico.TableColumn( this.deriveColumnNameFromCell(headerCells[i],i), true ) );
+      return columns;
+   },
+
+   convertToTableColumns: function(cols) {
+      var columns = new Array();
+      for ( var i = 0 ; i < cols.length ; i++ )
+         columns.push( new Rico.TableColumn( cols[i][0], cols[i][1] ) );
+   },
+
+   deriveColumnNameFromCell: function(cell,columnNumber) {
+      var cellContent = cell.innerText != undefined ? cell.innerText : cell.textContent;
+      return cellContent ? cellContent.toLowerCase().split(' ').join('_') : "col_" + columnNumber;
+   }
+};
+
+Rico.TableColumn = Class.create();
+
+Rico.TableColumn.UNSORTED  = 0;
+Rico.TableColumn.SORT_ASC  = "ASC";
+Rico.TableColumn.SORT_DESC = "DESC";
+
+Rico.TableColumn.prototype = {
+   initialize: function(name, sortable) {
+      this.name        = name;
+      this.sortable    = sortable;
+      this.currentSort = Rico.TableColumn.UNSORTED;
+   },
+
+   isSortable: function() {
+      return this.sortable;
+   },
+
+   isSorted: function() {
+      return this.currentSort != Rico.TableColumn.UNSORTED;
+   },
+
+   getSortDirection: function() {
+      return this.currentSort;
+   },
+
+   toggleSort: function() {
+      if ( this.currentSort == Rico.TableColumn.UNSORTED || this.currentSort == Rico.TableColumn.SORT_DESC )
+         this.currentSort = Rico.TableColumn.SORT_ASC;
+      else if ( this.currentSort == Rico.TableColumn.SORT_ASC )
+         this.currentSort = Rico.TableColumn.SORT_DESC;
+   },
+
+   setUnsorted: function(direction) {
+      this.setSorted(Rico.TableColumn.UNSORTED);
+   },
+
+   setSorted: function(direction) {
+      // direction must by one of Rico.TableColumn.UNSORTED, .SORT_ASC, or .SET_DESC...
+      this.currentSort = direction;
+   }
+
+};
+
+
+//-------------------- ricoUtil.js
+
+var RicoUtil = {
+
+   getElementsComputedStyle: function ( htmlElement, cssProperty, mozillaEquivalentCSS) {
+      if ( arguments.length == 2 )
+         mozillaEquivalentCSS = cssProperty;
+
+      var el = $(htmlElement);
+      if ( el.currentStyle )
+         return el.currentStyle[cssProperty];
+      else
+         return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozillaEquivalentCSS);
+   },
+
+   createXmlDocument : function() {
+      if (document.implementation && document.implementation.createDocument) {
+         var doc = document.implementation.createDocument("", "", null);
+
+         if (doc.readyState == null) {
+            doc.readyState = 1;
+            doc.addEventListener("load", function () {
+               doc.readyState = 4;
+               if (typeof doc.onreadystatechange == "function")
+                  doc.onreadystatechange();
+            }, false);
+         }
+
+         return doc;
+      }
+
+      if (window.ActiveXObject)
+          return Try.these(
+            function() { return new ActiveXObject('MSXML2.DomDocument')   },
+            function() { return new ActiveXObject('Microsoft.DomDocument')},
+            function() { return new ActiveXObject('MSXML.DomDocument')    },
+            function() { return new ActiveXObject('MSXML3.DomDocument')   }
+          ) || false;
+
+      return null;
+   },
+
+   getContentAsString: function( parentNode ) {
+      return parentNode.xml != undefined ? 
+         this._getContentAsStringIE(parentNode) :
+         this._getContentAsStringMozilla(parentNode);
+   },
+
+   _getContentAsStringIE: function(parentNode) {
+      var contentStr = "";
+      for ( var i = 0 ; i < parentNode.childNodes.length ; i++ )
+         contentStr += parentNode.childNodes[i].xml;
+      return contentStr;
+   },
+
+   _getContentAsStringMozilla: function(parentNode) {
+      var xmlSerializer = new XMLSerializer();
+      var contentStr = "";
+      for ( var i = 0 ; i < parentNode.childNodes.length ; i++ )
+         contentStr += xmlSerializer.serializeToString(parentNode.childNodes[i]);
+      return contentStr;
+   },
+
+   toViewportPosition: function(element) {
+      return this._toAbsolute(element,true);
+   },
+
+   toDocumentPosition: function(element) {
+      return this._toAbsolute(element,false);
+   },
+
+   /**
+    *  Compute the elements position in terms of the window viewport
+    *  so that it can be compared to the position of the mouse (dnd)
+    *  This is additions of all the offsetTop,offsetLeft values up the
+    *  offsetParent hierarchy, ...taking into account any scrollTop,
+    *  scrollLeft values along the way...
+    *
+    * IE has a bug reporting a correct offsetLeft of elements within a
+    * a relatively positioned parent!!!
+    **/
+   _toAbsolute: function(element,accountForDocScroll) {
+
+      if ( navigator.userAgent.toLowerCase().indexOf("msie") == -1 )
+         return this._toAbsoluteMozilla(element,accountForDocScroll);
+
+      var x = 0;
+      var y = 0;
+      var parent = element;
+      while ( parent ) {
+
+         var borderXOffset = 0;
+         var borderYOffset = 0;
+         if ( parent != element ) {
+            var borderXOffset = parseInt(this.getElementsComputedStyle(parent, "borderLeftWidth" ));
+            var borderYOffset = parseInt(this.getElementsComputedStyle(parent, "borderTopWidth" ));
+            borderXOffset = isNaN(borderXOffset) ? 0 : borderXOffset;
+            borderYOffset = isNaN(borderYOffset) ? 0 : borderYOffset;
+         }
+
+         x += parent.offsetLeft - parent.scrollLeft + borderXOffset;
+         y += parent.offsetTop - parent.scrollTop + borderYOffset;
+         parent = parent.offsetParent;
+      }
+
+      if ( accountForDocScroll ) {
+         x -= this.docScrollLeft();
+         y -= this.docScrollTop();
+      }
+
+      return { x:x, y:y };
+   },
+
+   /**
+    *  Mozilla did not report all of the parents up the hierarchy via the
+    *  offsetParent property that IE did.  So for the calculation of the
+    *  offsets we use the offsetParent property, but for the calculation of
+    *  the scrollTop/scrollLeft adjustments we navigate up via the parentNode
+    *  property instead so as to get the scroll offsets...
+    *
+    **/
+   _toAbsoluteMozilla: function(element,accountForDocScroll) {
+      var x = 0;
+      var y = 0;
+      var parent = element;
+      while ( parent ) {
+         x += parent.offsetLeft;
+         y += parent.offsetTop;
+         parent = parent.offsetParent;
+      }
+
+      parent = element;
+      while ( parent &&
+              parent != document.body &&
+              parent != document.documentElement ) {
+         if ( parent.scrollLeft  )
+            x -= parent.scrollLeft;
+         if ( parent.scrollTop )
+            y -= parent.scrollTop;
+         parent = parent.parentNode;
+      }
+
+      if ( accountForDocScroll ) {
+         x -= this.docScrollLeft();
+         y -= this.docScrollTop();
+      }
+
+      return { x:x, y:y };
+   },
+
+   docScrollLeft: function() {
+      if ( window.pageXOffset )
+         return window.pageXOffset;
+      else if ( document.documentElement && document.documentElement.scrollLeft )
+         return document.documentElement.scrollLeft;
+      else if ( document.body )
+         return document.body.scrollLeft;
+      else
+         return 0;
+   },
+
+   docScrollTop: function() {
+      if ( window.pageYOffset )
+         return window.pageYOffset;
+      else if ( document.documentElement && document.documentElement.scrollTop )
+         return document.documentElement.scrollTop;
+      else if ( document.body )
+         return document.body.scrollTop;
+      else
+         return 0;
+   }
+
+};
Index: branches/features/taskProcedureRework/web-app/js/prototype/scriptaculous.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/scriptaculous.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/scriptaculous.js	(revision 753)
@@ -0,0 +1,58 @@
+// script.aculo.us scriptaculous.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+// 
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+var Scriptaculous = {
+  Version: '1.8.0',
+  require: function(libraryName) {
+    // inserting via DOM fails in Safari 2.0, so brute force approach
+    document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
+  },
+  REQUIRED_PROTOTYPE: '1.6.0',
+  load: function() {
+    function convertVersionString(versionString){
+      var r = versionString.split('.');
+      return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
+    }
+ 
+    if((typeof Prototype=='undefined') || 
+       (typeof Element == 'undefined') || 
+       (typeof Element.Methods=='undefined') ||
+       (convertVersionString(Prototype.Version) < 
+        convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
+       throw("script.aculo.us requires the Prototype JavaScript framework >= " +
+        Scriptaculous.REQUIRED_PROTOTYPE);
+    
+    $A(document.getElementsByTagName("script")).findAll( function(s) {
+      return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
+    }).each( function(s) {
+      var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
+      var includes = s.src.match(/\?.*load=([a-z,]*)/);
+      (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
+       function(include) { Scriptaculous.require(path+include+'.js') });
+    });
+  }
+}
+
+Scriptaculous.load();
Index: branches/features/taskProcedureRework/web-app/js/prototype/slider.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/slider.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/slider.js	(revision 753)
@@ -0,0 +1,275 @@
+// script.aculo.us slider.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
+
+// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs 
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+if (!Control) var Control = { };
+
+// options:
+//  axis: 'vertical', or 'horizontal' (default)
+//
+// callbacks:
+//  onChange(value)
+//  onSlide(value)
+Control.Slider = Class.create({
+  initialize: function(handle, track, options) {
+    var slider = this;
+    
+    if (Object.isArray(handle)) {
+      this.handles = handle.collect( function(e) { return $(e) });
+    } else {
+      this.handles = [$(handle)];
+    }
+    
+    this.track   = $(track);
+    this.options = options || { };
+
+    this.axis      = this.options.axis || 'horizontal';
+    this.increment = this.options.increment || 1;
+    this.step      = parseInt(this.options.step || '1');
+    this.range     = this.options.range || $R(0,1);
+    
+    this.value     = 0; // assure backwards compat
+    this.values    = this.handles.map( function() { return 0 });
+    this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
+    this.options.startSpan = $(this.options.startSpan || null);
+    this.options.endSpan   = $(this.options.endSpan || null);
+
+    this.restricted = this.options.restricted || false;
+
+    this.maximum   = this.options.maximum || this.range.end;
+    this.minimum   = this.options.minimum || this.range.start;
+
+    // Will be used to align the handle onto the track, if necessary
+    this.alignX = parseInt(this.options.alignX || '0');
+    this.alignY = parseInt(this.options.alignY || '0');
+    
+    this.trackLength = this.maximumOffset() - this.minimumOffset();
+
+    this.handleLength = this.isVertical() ? 
+      (this.handles[0].offsetHeight != 0 ? 
+        this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) : 
+      (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : 
+        this.handles[0].style.width.replace(/px$/,""));
+
+    this.active   = false;
+    this.dragging = false;
+    this.disabled = false;
+
+    if (this.options.disabled) this.setDisabled();
+
+    // Allowed values array
+    this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
+    if (this.allowedValues) {
+      this.minimum = this.allowedValues.min();
+      this.maximum = this.allowedValues.max();
+    }
+
+    this.eventMouseDown = this.startDrag.bindAsEventListener(this);
+    this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
+    this.eventMouseMove = this.update.bindAsEventListener(this);
+
+    // Initialize handles in reverse (make sure first handle is active)
+    this.handles.each( function(h,i) {
+      i = slider.handles.length-1-i;
+      slider.setValue(parseFloat(
+        (Object.isArray(slider.options.sliderValue) ? 
+          slider.options.sliderValue[i] : slider.options.sliderValue) || 
+         slider.range.start), i);
+      h.makePositioned().observe("mousedown", slider.eventMouseDown);
+    });
+    
+    this.track.observe("mousedown", this.eventMouseDown);
+    document.observe("mouseup", this.eventMouseUp);
+    document.observe("mousemove", this.eventMouseMove);
+    
+    this.initialized = true;
+  },
+  dispose: function() {
+    var slider = this;    
+    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
+    Event.stopObserving(document, "mouseup", this.eventMouseUp);
+    Event.stopObserving(document, "mousemove", this.eventMouseMove);
+    this.handles.each( function(h) {
+      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
+    });
+  },
+  setDisabled: function(){
+    this.disabled = true;
+  },
+  setEnabled: function(){
+    this.disabled = false;
+  },  
+  getNearestValue: function(value){
+    if (this.allowedValues){
+      if (value >= this.allowedValues.max()) return(this.allowedValues.max());
+      if (value <= this.allowedValues.min()) return(this.allowedValues.min());
+      
+      var offset = Math.abs(this.allowedValues[0] - value);
+      var newValue = this.allowedValues[0];
+      this.allowedValues.each( function(v) {
+        var currentOffset = Math.abs(v - value);
+        if (currentOffset <= offset){
+          newValue = v;
+          offset = currentOffset;
+        } 
+      });
+      return newValue;
+    }
+    if (value > this.range.end) return this.range.end;
+    if (value < this.range.start) return this.range.start;
+    return value;
+  },
+  setValue: function(sliderValue, handleIdx){
+    if (!this.active) {
+      this.activeHandleIdx = handleIdx || 0;
+      this.activeHandle    = this.handles[this.activeHandleIdx];
+      this.updateStyles();
+    }
+    handleIdx = handleIdx || this.activeHandleIdx || 0;
+    if (this.initialized && this.restricted) {
+      if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
+        sliderValue = this.values[handleIdx-1];
+      if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
+        sliderValue = this.values[handleIdx+1];
+    }
+    sliderValue = this.getNearestValue(sliderValue);
+    this.values[handleIdx] = sliderValue;
+    this.value = this.values[0]; // assure backwards compat
+    
+    this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = 
+      this.translateToPx(sliderValue);
+    
+    this.drawSpans();
+    if (!this.dragging || !this.event) this.updateFinished();
+  },
+  setValueBy: function(delta, handleIdx) {
+    this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, 
+      handleIdx || this.activeHandleIdx || 0);
+  },
+  translateToPx: function(value) {
+    return Math.round(
+      ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * 
+      (value - this.range.start)) + "px";
+  },
+  translateToValue: function(offset) {
+    return ((offset/(this.trackLength-this.handleLength) * 
+      (this.range.end-this.range.start)) + this.range.start);
+  },
+  getRange: function(range) {
+    var v = this.values.sortBy(Prototype.K); 
+    range = range || 0;
+    return $R(v[range],v[range+1]);
+  },
+  minimumOffset: function(){
+    return(this.isVertical() ? this.alignY : this.alignX);
+  },
+  maximumOffset: function(){
+    return(this.isVertical() ? 
+      (this.track.offsetHeight != 0 ? this.track.offsetHeight :
+        this.track.style.height.replace(/px$/,"")) - this.alignY : 
+      (this.track.offsetWidth != 0 ? this.track.offsetWidth : 
+        this.track.style.width.replace(/px$/,"")) - this.alignX);
+  },  
+  isVertical:  function(){
+    return (this.axis == 'vertical');
+  },
+  drawSpans: function() {
+    var slider = this;
+    if (this.spans)
+      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
+    if (this.options.startSpan)
+      this.setSpan(this.options.startSpan,
+        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
+    if (this.options.endSpan)
+      this.setSpan(this.options.endSpan, 
+        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
+  },
+  setSpan: function(span, range) {
+    if (this.isVertical()) {
+      span.style.top = this.translateToPx(range.start);
+      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
+    } else {
+      span.style.left = this.translateToPx(range.start);
+      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
+    }
+  },
+  updateStyles: function() {
+    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
+    Element.addClassName(this.activeHandle, 'selected');
+  },
+  startDrag: function(event) {
+    if (Event.isLeftClick(event)) {
+      if (!this.disabled){
+        this.active = true;
+        
+        var handle = Event.element(event);
+        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
+        var track = handle;
+        if (track==this.track) {
+          var offsets  = Position.cumulativeOffset(this.track); 
+          this.event = event;
+          this.setValue(this.translateToValue( 
+           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
+          ));
+          var offsets  = Position.cumulativeOffset(this.activeHandle);
+          this.offsetX = (pointer[0] - offsets[0]);
+          this.offsetY = (pointer[1] - offsets[1]);
+        } else {
+          // find the handle (prevents issues with Safari)
+          while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
+            handle = handle.parentNode;
+            
+          if (this.handles.indexOf(handle)!=-1) {
+            this.activeHandle    = handle;
+            this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
+            this.updateStyles();
+            
+            var offsets  = Position.cumulativeOffset(this.activeHandle);
+            this.offsetX = (pointer[0] - offsets[0]);
+            this.offsetY = (pointer[1] - offsets[1]);
+          }
+        }
+      }
+      Event.stop(event);
+    }
+  },
+  update: function(event) {
+   if (this.active) {
+      if (!this.dragging) this.dragging = true;
+      this.draw(event);
+      if (Prototype.Browser.WebKit) window.scrollBy(0,0);
+      Event.stop(event);
+   }
+  },
+  draw: function(event) {
+    var pointer = [Event.pointerX(event), Event.pointerY(event)];
+    var offsets = Position.cumulativeOffset(this.track);
+    pointer[0] -= this.offsetX + offsets[0];
+    pointer[1] -= this.offsetY + offsets[1];
+    this.event = event;
+    this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
+    if (this.initialized && this.options.onSlide)
+      this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
+  },
+  endDrag: function(event) {
+    if (this.active && this.dragging) {
+      this.finishDrag(event, true);
+      Event.stop(event);
+    }
+    this.active = false;
+    this.dragging = false;
+  },  
+  finishDrag: function(event, success) {
+    this.active = false;
+    this.dragging = false;
+    this.updateFinished();
+  },
+  updateFinished: function() {
+    if (this.initialized && this.options.onChange) 
+      this.options.onChange(this.values.length>1 ? this.values : this.value, this);
+    this.event = null;
+  }
+});
Index: branches/features/taskProcedureRework/web-app/js/prototype/sound.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/sound.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/sound.js	(revision 753)
@@ -0,0 +1,55 @@
+// script.aculo.us sound.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//
+// Based on code created by Jules Gravinese (http://www.webveteran.com/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+Sound = {
+  tracks: {},
+  _enabled: true,
+  template:
+    new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
+  enable: function(){
+    Sound._enabled = true;
+  },
+  disable: function(){
+    Sound._enabled = false;
+  },
+  play: function(url){
+    if(!Sound._enabled) return;
+    var options = Object.extend({
+      track: 'global', url: url, replace: false
+    }, arguments[1] || {});
+    
+    if(options.replace && this.tracks[options.track]) {
+      $R(0, this.tracks[options.track].id).each(function(id){
+        var sound = $('sound_'+options.track+'_'+id);
+        sound.Stop && sound.Stop();
+        sound.remove();
+      })
+      this.tracks[options.track] = null;
+    }
+      
+    if(!this.tracks[options.track])
+      this.tracks[options.track] = { id: 0 }
+    else
+      this.tracks[options.track].id++;
+      
+    options.id = this.tracks[options.track].id;
+    $$('body')[0].insert( 
+      Prototype.Browser.IE ? new Element('bgsound',{
+        id: 'sound_'+options.track+'_'+options.id,
+        src: options.url, loop: 1, autostart: true
+      }) : Sound.template.evaluate(options));
+  }
+};
+
+if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
+  if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
+    Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
+  else
+    Sound.play = function(){}
+}
Index: branches/features/taskProcedureRework/web-app/js/prototype/unittest.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/prototype/unittest.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/prototype/unittest.js	(revision 753)
@@ -0,0 +1,568 @@
+// script.aculo.us unittest.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
+
+// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+//           (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
+//           (c) 2005-2007 Michael Schuerig (http://www.schuerig.de/michael/)
+//
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
+// For details, see the script.aculo.us web site: http://script.aculo.us/
+
+// experimental, Firefox-only
+Event.simulateMouse = function(element, eventName) {
+  var options = Object.extend({
+    pointerX: 0,
+    pointerY: 0,
+    buttons:  0,
+    ctrlKey:  false,
+    altKey:   false,
+    shiftKey: false,
+    metaKey:  false
+  }, arguments[2] || {});
+  var oEvent = document.createEvent("MouseEvents");
+  oEvent.initMouseEvent(eventName, true, true, document.defaultView, 
+    options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY, 
+    options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element));
+  
+  if(this.mark) Element.remove(this.mark);
+  this.mark = document.createElement('div');
+  this.mark.appendChild(document.createTextNode(" "));
+  document.body.appendChild(this.mark);
+  this.mark.style.position = 'absolute';
+  this.mark.style.top = options.pointerY + "px";
+  this.mark.style.left = options.pointerX + "px";
+  this.mark.style.width = "5px";
+  this.mark.style.height = "5px;";
+  this.mark.style.borderTop = "1px solid red;"
+  this.mark.style.borderLeft = "1px solid red;"
+  
+  if(this.step)
+    alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
+  
+  $(element).dispatchEvent(oEvent);
+};
+
+// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
+// You need to downgrade to 1.0.4 for now to get this working
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
+Event.simulateKey = function(element, eventName) {
+  var options = Object.extend({
+    ctrlKey: false,
+    altKey: false,
+    shiftKey: false,
+    metaKey: false,
+    keyCode: 0,
+    charCode: 0
+  }, arguments[2] || {});
+
+  var oEvent = document.createEvent("KeyEvents");
+  oEvent.initKeyEvent(eventName, true, true, window, 
+    options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
+    options.keyCode, options.charCode );
+  $(element).dispatchEvent(oEvent);
+};
+
+Event.simulateKeys = function(element, command) {
+  for(var i=0; i<command.length; i++) {
+    Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
+  }
+};
+
+var Test = {}
+Test.Unit = {};
+
+// security exception workaround
+Test.Unit.inspect = Object.inspect;
+
+Test.Unit.Logger = Class.create();
+Test.Unit.Logger.prototype = {
+  initialize: function(log) {
+    this.log = $(log);
+    if (this.log) {
+      this._createLogTable();
+    }
+  },
+  start: function(testName) {
+    if (!this.log) return;
+    this.testName = testName;
+    this.lastLogLine = document.createElement('tr');
+    this.statusCell = document.createElement('td');
+    this.nameCell = document.createElement('td');
+    this.nameCell.className = "nameCell";
+    this.nameCell.appendChild(document.createTextNode(testName));
+    this.messageCell = document.createElement('td');
+    this.lastLogLine.appendChild(this.statusCell);
+    this.lastLogLine.appendChild(this.nameCell);
+    this.lastLogLine.appendChild(this.messageCell);
+    this.loglines.appendChild(this.lastLogLine);
+  },
+  finish: function(status, summary) {
+    if (!this.log) return;
+    this.lastLogLine.className = status;
+    this.statusCell.innerHTML = status;
+    this.messageCell.innerHTML = this._toHTML(summary);
+    this.addLinksToResults();
+  },
+  message: function(message) {
+    if (!this.log) return;
+    this.messageCell.innerHTML = this._toHTML(message);
+  },
+  summary: function(summary) {
+    if (!this.log) return;
+    this.logsummary.innerHTML = this._toHTML(summary);
+  },
+  _createLogTable: function() {
+    this.log.innerHTML =
+    '<div id="logsummary"></div>' +
+    '<table id="logtable">' +
+    '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
+    '<tbody id="loglines"></tbody>' +
+    '</table>';
+    this.logsummary = $('logsummary')
+    this.loglines = $('loglines');
+  },
+  _toHTML: function(txt) {
+    return txt.escapeHTML().replace(/\n/g,"<br/>");
+  },
+  addLinksToResults: function(){ 
+    $$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
+      td.title = "Run only this test"
+      Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
+    });
+    $$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
+      td.title = "Run all tests"
+      Event.observe(td, 'click', function(){ window.location.search = "";});
+    });
+  }
+}
+
+Test.Unit.Runner = Class.create();
+Test.Unit.Runner.prototype = {
+  initialize: function(testcases) {
+    this.options = Object.extend({
+      testLog: 'testlog'
+    }, arguments[1] || {});
+    this.options.resultsURL = this.parseResultsURLQueryParameter();
+    this.options.tests      = this.parseTestsQueryParameter();
+    if (this.options.testLog) {
+      this.options.testLog = $(this.options.testLog) || null;
+    }
+    if(this.options.tests) {
+      this.tests = [];
+      for(var i = 0; i < this.options.tests.length; i++) {
+        if(/^test/.test(this.options.tests[i])) {
+          this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
+        }
+      }
+    } else {
+      if (this.options.test) {
+        this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
+      } else {
+        this.tests = [];
+        for(var testcase in testcases) {
+          if(/^test/.test(testcase)) {
+            this.tests.push(
+               new Test.Unit.Testcase(
+                 this.options.context ? ' -> ' + this.options.titles[testcase] : testcase, 
+                 testcases[testcase], testcases["setup"], testcases["teardown"]
+               ));
+          }
+        }
+      }
+    }
+    this.currentTest = 0;
+    this.logger = new Test.Unit.Logger(this.options.testLog);
+    setTimeout(this.runTests.bind(this), 1000);
+  },
+  parseResultsURLQueryParameter: function() {
+    return window.location.search.parseQuery()["resultsURL"];
+  },
+  parseTestsQueryParameter: function(){
+    if (window.location.search.parseQuery()["tests"]){
+        return window.location.search.parseQuery()["tests"].split(',');
+    };
+  },
+  // Returns:
+  //  "ERROR" if there was an error,
+  //  "FAILURE" if there was a failure, or
+  //  "SUCCESS" if there was neither
+  getResult: function() {
+    var hasFailure = false;
+    for(var i=0;i<this.tests.length;i++) {
+      if (this.tests[i].errors > 0) {
+        return "ERROR";
+      }
+      if (this.tests[i].failures > 0) {
+        hasFailure = true;
+      }
+    }
+    if (hasFailure) {
+      return "FAILURE";
+    } else {
+      return "SUCCESS";
+    }
+  },
+  postResults: function() {
+    if (this.options.resultsURL) {
+      new Ajax.Request(this.options.resultsURL, 
+        { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
+    }
+  },
+  runTests: function() {
+    var test = this.tests[this.currentTest];
+    if (!test) {
+      // finished!
+      this.postResults();
+      this.logger.summary(this.summary());
+      return;
+    }
+    if(!test.isWaiting) {
+      this.logger.start(test.name);
+    }
+    test.run();
+    if(test.isWaiting) {
+      this.logger.message("Waiting for " + test.timeToWait + "ms");
+      setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
+    } else {
+      this.logger.finish(test.status(), test.summary());
+      this.currentTest++;
+      // tail recursive, hopefully the browser will skip the stackframe
+      this.runTests();
+    }
+  },
+  summary: function() {
+    var assertions = 0;
+    var failures = 0;
+    var errors = 0;
+    var messages = [];
+    for(var i=0;i<this.tests.length;i++) {
+      assertions +=   this.tests[i].assertions;
+      failures   +=   this.tests[i].failures;
+      errors     +=   this.tests[i].errors;
+    }
+    return (
+      (this.options.context ? this.options.context + ': ': '') + 
+      this.tests.length + " tests, " + 
+      assertions + " assertions, " + 
+      failures   + " failures, " +
+      errors     + " errors");
+  }
+}
+
+Test.Unit.Assertions = Class.create();
+Test.Unit.Assertions.prototype = {
+  initialize: function() {
+    this.assertions = 0;
+    this.failures   = 0;
+    this.errors     = 0;
+    this.messages   = [];
+  },
+  summary: function() {
+    return (
+      this.assertions + " assertions, " + 
+      this.failures   + " failures, " +
+      this.errors     + " errors" + "\n" +
+      this.messages.join("\n"));
+  },
+  pass: function() {
+    this.assertions++;
+  },
+  fail: function(message) {
+    this.failures++;
+    this.messages.push("Failure: " + message);
+  },
+  info: function(message) {
+    this.messages.push("Info: " + message);
+  },
+  error: function(error) {
+    this.errors++;
+    this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
+  },
+  status: function() {
+    if (this.failures > 0) return 'failed';
+    if (this.errors > 0) return 'error';
+    return 'passed';
+  },
+  assert: function(expression) {
+    var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
+    try { expression ? this.pass() : 
+      this.fail(message); }
+    catch(e) { this.error(e); }
+  },
+  assertEqual: function(expected, actual) {
+    var message = arguments[2] || "assertEqual";
+    try { (expected == actual) ? this.pass() :
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) + 
+        '", actual "' + Test.Unit.inspect(actual) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertInspect: function(expected, actual) {
+    var message = arguments[2] || "assertInspect";
+    try { (expected == actual.inspect()) ? this.pass() :
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) + 
+        '", actual "' + Test.Unit.inspect(actual) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertEnumEqual: function(expected, actual) {
+    var message = arguments[2] || "assertEnumEqual";
+    try { $A(expected).length == $A(actual).length && 
+      expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
+        this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) + 
+          ', actual ' + Test.Unit.inspect(actual)); }
+    catch(e) { this.error(e); }
+  },
+  assertNotEqual: function(expected, actual) {
+    var message = arguments[2] || "assertNotEqual";
+    try { (expected != actual) ? this.pass() : 
+      this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertIdentical: function(expected, actual) { 
+    var message = arguments[2] || "assertIdentical"; 
+    try { (expected === actual) ? this.pass() : 
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
+        '", actual "' + Test.Unit.inspect(actual) + '"'); } 
+    catch(e) { this.error(e); } 
+  },
+  assertNotIdentical: function(expected, actual) { 
+    var message = arguments[2] || "assertNotIdentical"; 
+    try { !(expected === actual) ? this.pass() : 
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
+        '", actual "' + Test.Unit.inspect(actual) + '"'); } 
+    catch(e) { this.error(e); } 
+  },
+  assertNull: function(obj) {
+    var message = arguments[1] || 'assertNull'
+    try { (obj==null) ? this.pass() : 
+      this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertMatch: function(expected, actual) {
+    var message = arguments[2] || 'assertMatch';
+    var regex = new RegExp(expected);
+    try { (regex.exec(actual)) ? this.pass() :
+      this.fail(message + ' : regex: "' +  Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertHidden: function(element) {
+    var message = arguments[1] || 'assertHidden';
+    this.assertEqual("none", element.style.display, message);
+  },
+  assertNotNull: function(object) {
+    var message = arguments[1] || 'assertNotNull';
+    this.assert(object != null, message);
+  },
+  assertType: function(expected, actual) {
+    var message = arguments[2] || 'assertType';
+    try { 
+      (actual.constructor == expected) ? this.pass() : 
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
+        '", actual "' + (actual.constructor) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertNotOfType: function(expected, actual) {
+    var message = arguments[2] || 'assertNotOfType';
+    try { 
+      (actual.constructor != expected) ? this.pass() : 
+      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +  
+        '", actual "' + (actual.constructor) + '"'); }
+    catch(e) { this.error(e); }
+  },
+  assertInstanceOf: function(expected, actual) {
+    var message = arguments[2] || 'assertInstanceOf';
+    try { 
+      (actual instanceof expected) ? this.pass() : 
+      this.fail(message + ": object was not an instance of the expected type"); }
+    catch(e) { this.error(e); } 
+  },
+  assertNotInstanceOf: function(expected, actual) {
+    var message = arguments[2] || 'assertNotInstanceOf';
+    try { 
+      !(actual instanceof expected) ? this.pass() : 
+      this.fail(message + ": object was an instance of the not expected type"); }
+    catch(e) { this.error(e); } 
+  },
+  assertRespondsTo: function(method, obj) {
+    var message = arguments[2] || 'assertRespondsTo';
+    try {
+      (obj[method] && typeof obj[method] == 'function') ? this.pass() : 
+      this.fail(message + ": object doesn't respond to [" + method + "]"); }
+    catch(e) { this.error(e); }
+  },
+  assertReturnsTrue: function(method, obj) {
+    var message = arguments[2] || 'assertReturnsTrue';
+    try {
+      var m = obj[method];
+      if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
+      m() ? this.pass() : 
+      this.fail(message + ": method returned false"); }
+    catch(e) { this.error(e); }
+  },
+  assertReturnsFalse: function(method, obj) {
+    var message = arguments[2] || 'assertReturnsFalse';
+    try {
+      var m = obj[method];
+      if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
+      !m() ? this.pass() : 
+      this.fail(message + ": method returned true"); }
+    catch(e) { this.error(e); }
+  },
+  assertRaise: function(exceptionName, method) {
+    var message = arguments[2] || 'assertRaise';
+    try { 
+      method();
+      this.fail(message + ": exception expected but none was raised"); }
+    catch(e) {
+      ((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e); 
+    }
+  },
+  assertElementsMatch: function() {
+    var expressions = $A(arguments), elements = $A(expressions.shift());
+    if (elements.length != expressions.length) {
+      this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions');
+      return false;
+    }
+    elements.zip(expressions).all(function(pair, index) {
+      var element = $(pair.first()), expression = pair.last();
+      if (element.match(expression)) return true;
+      this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect());
+    }.bind(this)) && this.pass();
+  },
+  assertElementMatches: function(element, expression) {
+    this.assertElementsMatch([element], expression);
+  },
+  benchmark: function(operation, iterations) {
+    var startAt = new Date();
+    (iterations || 1).times(operation);
+    var timeTaken = ((new Date())-startAt);
+    this.info((arguments[2] || 'Operation') + ' finished ' + 
+       iterations + ' iterations in ' + (timeTaken/1000)+'s' );
+    return timeTaken;
+  },
+  _isVisible: function(element) {
+    element = $(element);
+    if(!element.parentNode) return true;
+    this.assertNotNull(element);
+    if(element.style && Element.getStyle(element, 'display') == 'none')
+      return false;
+    
+    return this._isVisible(element.parentNode);
+  },
+  assertNotVisible: function(element) {
+    this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
+  },
+  assertVisible: function(element) {
+    this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
+  },
+  benchmark: function(operation, iterations) {
+    var startAt = new Date();
+    (iterations || 1).times(operation);
+    var timeTaken = ((new Date())-startAt);
+    this.info((arguments[2] || 'Operation') + ' finished ' + 
+       iterations + ' iterations in ' + (timeTaken/1000)+'s' );
+    return timeTaken;
+  }
+}
+
+Test.Unit.Testcase = Class.create();
+Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
+  initialize: function(name, test, setup, teardown) {
+    Test.Unit.Assertions.prototype.initialize.bind(this)();
+    this.name           = name;
+    
+    if(typeof test == 'string') {
+      test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,');
+      test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)');
+      this.test = function() {
+        eval('with(this){'+test+'}');
+      }
+    } else {
+      this.test = test || function() {};
+    }
+    
+    this.setup          = setup || function() {};
+    this.teardown       = teardown || function() {};
+    this.isWaiting      = false;
+    this.timeToWait     = 1000;
+  },
+  wait: function(time, nextPart) {
+    this.isWaiting = true;
+    this.test = nextPart;
+    this.timeToWait = time;
+  },
+  run: function() {
+    try {
+      try {
+        if (!this.isWaiting) this.setup.bind(this)();
+        this.isWaiting = false;
+        this.test.bind(this)();
+      } finally {
+        if(!this.isWaiting) {
+          this.teardown.bind(this)();
+        }
+      }
+    }
+    catch(e) { this.error(e); }
+  }
+});
+
+// *EXPERIMENTAL* BDD-style testing to please non-technical folk
+// This draws many ideas from RSpec http://rspec.rubyforge.org/
+
+Test.setupBDDExtensionMethods = function(){
+  var METHODMAP = {
+    shouldEqual:     'assertEqual',
+    shouldNotEqual:  'assertNotEqual',
+    shouldEqualEnum: 'assertEnumEqual',
+    shouldBeA:       'assertType',
+    shouldNotBeA:    'assertNotOfType',
+    shouldBeAn:      'assertType',
+    shouldNotBeAn:   'assertNotOfType',
+    shouldBeNull:    'assertNull',
+    shouldNotBeNull: 'assertNotNull',
+    
+    shouldBe:        'assertReturnsTrue',
+    shouldNotBe:     'assertReturnsFalse',
+    shouldRespondTo: 'assertRespondsTo'
+  };
+  var makeAssertion = function(assertion, args, object) { 
+   	this[assertion].apply(this,(args || []).concat([object]));
+  }
+  
+  Test.BDDMethods = {};   
+  $H(METHODMAP).each(function(pair) { 
+    Test.BDDMethods[pair.key] = function() { 
+       var args = $A(arguments); 
+       var scope = args.shift(); 
+       makeAssertion.apply(scope, [pair.value, args, this]); }; 
+  });
+  
+  [Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
+    function(p){ Object.extend(p, Test.BDDMethods) }
+  );
+}
+
+Test.context = function(name, spec, log){
+  Test.setupBDDExtensionMethods();
+  
+  var compiledSpec = {};
+  var titles = {};
+  for(specName in spec) {
+    switch(specName){
+      case "setup":
+      case "teardown":
+        compiledSpec[specName] = spec[specName];
+        break;
+      default:
+        var testName = 'test'+specName.gsub(/\s+/,'-').camelize();
+        var body = spec[specName].toString().split('\n').slice(1);
+        if(/^\{/.test(body[0])) body = body.slice(1);
+        body.pop();
+        body = body.map(function(statement){ 
+          return statement.strip()
+        });
+        compiledSpec[testName] = body.join('\n');
+        titles[testName] = specName;
+    }
+  }
+  new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name });
+};
Index: branches/features/taskProcedureRework/web-app/js/taskQuickSearchPane.js
===================================================================
--- branches/features/taskProcedureRework/web-app/js/taskQuickSearchPane.js	(revision 753)
+++ branches/features/taskProcedureRework/web-app/js/taskQuickSearchPane.js	(revision 753)
@@ -0,0 +1,33 @@
+
+function updateQuickSearchSelection() {
+    var personsTasksSelectionIds = ['personLabel', 'personSelection', 'completedLabel', 'completedSelection'];
+    var helpBalloonSpanIds = ['allTasksHelp', 'personsTasksHelp', 'personsImmediateCalloutsHelp'];
+    var val = $("quickSearchSelect").value;
+
+    $A(HelpBalloon._balloons).invoke('hide'); // Hide any open balloons.
+    helpBalloonSpanIds.each(Element.hide); // Hide all help icons.
+
+    switch(val)
+    {
+        case 'allTasks':
+            showUtil('allTasksHelp');
+            hideArrayUtil(personsTasksSelectionIds);
+            break;
+        case 'personsTasks':
+            showUtil('personsTasksHelp');
+            showArrayUtil(personsTasksSelectionIds);
+            break;
+        case 'personsImmediateCallouts':
+            showUtil('personsImmediateCalloutsHelp');
+            showArrayUtil(personsTasksSelectionIds);
+            break;
+    }
+
+}
+
+Event.observe(window, 'load', function() {
+    updateQuickSearchSelection(); // Initial page load.
+    $A(HelpBalloon._balloons).invoke('show'); // Work around for offset balloon when using a pane in IE.
+    $A(HelpBalloon._balloons).invoke('hide'); // Work around for offset balloon when using a pane in IE.
+    $("quickSearchSelect").observe('change', updateQuickSearchSelection); // Register onchange handler.
+});
Index: branches/features/taskProcedureRework/web-app/reports/assetDetail.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/assetDetail.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/assetDetail.jrxml	(revision 753)
@@ -0,0 +1,253 @@
+<?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="reportName" language="groovy" pageWidth="595" pageHeight="842" whenNoDataType="NoDataSection" columnWidth="577" leftMargin="9" rightMargin="9" topMargin="9" bottomMargin="9" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.5"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="0"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="GroupHeader" isDefault="false" hAlign="Center">
+		<box topPadding="0" bottomPadding="0">
+			<topPen lineWidth="0.0"/>
+			<bottomPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="DetailBorder" isDefault="false">
+		<box topPadding="2" leftPadding="1" bottomPadding="2" rightPadding="1">
+			<topPen lineWidth="0.5"/>
+			<leftPen lineWidth="0.5"/>
+			<bottomPen lineWidth="0.5"/>
+			<rightPen lineWidth="0.5"/>
+		</box>
+	</style>
+	<subDataset name="dataset1">
+		<queryString language="SQL">
+			<![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]>
+		</queryString>
+		<field name="description" class="java.lang.String"/>
+		<field name="name" class="java.lang.String"/>
+		<field name="comment" class="java.lang.String"/>
+		<field name="attribValue" class="java.lang.String"/>
+		<field name="attribType" class="java.lang.String"/>
+		<group name="assetName">
+			<groupExpression><![CDATA[$F{name}]]></groupExpression>
+		</group>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="section" class="java.lang.String"/>
+	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
+		<defaultValueExpression><![CDATA["C:\\Documents and Settings\\kromhoutg\\My Documents\\reports\\"]]></defaultValueExpression>
+	</parameter>
+	<parameter name="site" class="java.lang.String"/>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="name" class="java.lang.String"/>
+	<field name="description" class="java.lang.String"/>
+	<field name="attribValue" class="java.lang.String"/>
+	<field name="attribType" class="java.lang.String"/>
+	<field name="comment" class="java.lang.String"/>
+	<group name="assetName" keepTogether="true">
+		<groupExpression><![CDATA[$F{name}]]></groupExpression>
+		<groupHeader>
+			<band height="52">
+				<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+					<reportElement stretchType="RelativeToTallestObject" x="9" y="24" width="331" height="20" isPrintWhenDetailOverflows="true"/>
+					<textElement>
+						<font fontName="Serif" size="8"/>
+					</textElement>
+					<textFieldExpression class="java.lang.String"><![CDATA[$F{description}]]></textFieldExpression>
+				</textField>
+				<textField isStretchWithOverflow="true">
+					<reportElement stretchType="RelativeToTallestObject" mode="Opaque" x="9" y="4" width="331" height="20" isPrintWhenDetailOverflows="true" backcolor="#FFFF33"/>
+					<textElement>
+						<font fontName="Serif" size="10" isBold="true"/>
+					</textElement>
+					<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+				</textField>
+				<textField isStretchWithOverflow="true">
+					<reportElement stretchType="RelativeToTallestObject" x="352" y="12" width="203" height="40" isPrintWhenDetailOverflows="true"/>
+					<textElement>
+						<font fontName="Serif" size="8"/>
+					</textElement>
+					<textFieldExpression class="java.lang.String"><![CDATA[$F{comment}]]></textFieldExpression>
+				</textField>
+			</band>
+		</groupHeader>
+		<groupFooter>
+			<band/>
+		</groupFooter>
+	</group>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="60" splitType="Stretch">
+			<textField isStretchWithOverflow="true">
+				<reportElement key="staticText-1" stretchType="RelativeToTallestObject" x="352" y="9" width="225" height="20" isPrintWhenDetailOverflows="true"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="14"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField isStretchWithOverflow="true">
+				<reportElement stretchType="RelativeToTallestObject" x="352" y="29" width="225" height="15" isPrintWhenDetailOverflows="true"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif" size="10"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Site: "+$P{site}+", "+"Section: "+$P{section}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="24" splitType="Stretch">
+			<printWhenExpression><![CDATA[$F{attribValue}]]></printWhenExpression>
+			<elementGroup>
+				<textField isStretchWithOverflow="true">
+					<reportElement style="DetailBorder" stretchType="RelativeToTallestObject" x="138" y="2" width="288" height="20" isPrintWhenDetailOverflows="true"/>
+					<textElement textAlignment="Center" verticalAlignment="Middle">
+						<font fontName="Serif" size="8"/>
+					</textElement>
+					<textFieldExpression class="java.lang.String"><![CDATA[$F{attribValue}]]></textFieldExpression>
+				</textField>
+				<textField isStretchWithOverflow="true">
+					<reportElement stretchType="RelativeToTallestObject" x="9" y="2" width="129" height="20" isPrintWhenDetailOverflows="true"/>
+					<textElement>
+						<font fontName="Serif" size="8" isBold="true" isUnderline="false"/>
+					</textElement>
+					<textFieldExpression class="java.lang.String"><![CDATA[$F{attribType}+":"]]></textFieldExpression>
+				</textField>
+			</elementGroup>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="28" splitType="Stretch">
+			<textField isStretchWithOverflow="true" pattern="dd-MMM-yyyy">
+				<reportElement stretchType="RelativeToTallestObject" x="50" y="2" width="200" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement stretchType="RelativeToTallestObject" x="537" y="14" width="40" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement stretchType="RelativeToTallestObject" x="0" y="2" width="50" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement stretchType="RelativeToTallestObject" x="50" y="14" width="200" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement stretchType="RelativeToTallestObject" x="0" y="14" width="50" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement stretchType="RelativeToTallestObject" x="457" y="14" width="80" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="28">
+			<textField isStretchWithOverflow="true" evaluationTime="Report">
+				<reportElement stretchType="RelativeToTallestObject" x="537" y="14" width="40" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="dd-MMM-yyyy">
+				<reportElement stretchType="RelativeToTallestObject" x="50" y="2" width="200" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement stretchType="RelativeToTallestObject" x="0" y="2" width="50" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement stretchType="RelativeToTallestObject" x="0" y="14" width="50" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement stretchType="RelativeToTallestObject" x="50" y="14" width="200" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement stretchType="RelativeToTallestObject" x="457" y="14" width="80" height="12" isPrintWhenDetailOverflows="true"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<printWhenExpression><![CDATA[""]]></printWhenExpression>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="555" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="14" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="555" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/assetRegister.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/assetRegister.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/assetRegister.jrxml	(revision 753)
@@ -0,0 +1,509 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="824" leftMargin="9" rightMargin="9" topMargin="9" bottomMargin="9" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.5"/>
+	<property name="ireport.x" value="15"/>
+	<property name="ireport.y" value="729"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="table" isDefault="false">
+		<box>
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="1.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="1.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#F0F8FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#BFE1FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" pattern="">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<subDataset name="dataset1">
+		<queryString language="SQL">
+			<![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]>
+		</queryString>
+		<field name="name" class="java.lang.String"/>
+		<field name="description" class="java.lang.String"/>
+		<field name="comment" class="java.lang.String"/>
+		<field name="Serial Number" class="java.lang.String"/>
+		<field name="Model Number" class="java.lang.String"/>
+		<field name="Manufacturer" class="java.lang.String"/>
+		<field name="ecr" class="java.lang.String"/>
+		<field name="Risk Level" class="java.lang.String"/>
+		<field name="Safe Work Procedure" class="java.lang.String"/>
+		<field name="Regulatory Requirement" class="java.lang.String"/>
+		<field name="Maintenance % Completion" class="java.lang.String"/>
+		<field name="Registration Required" class="java.lang.String"/>
+		<field name="Registration Expiry Date" class="java.lang.String"/>
+		<field name="Asset Number" class="java.lang.String"/>
+		<group name="assetName">
+			<groupExpression><![CDATA[$F{name}]]></groupExpression>
+		</group>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
+		<defaultValueExpression><![CDATA["C:\\Documents and Settings\\kromhoutg\\My Documents\\reports\\"]]></defaultValueExpression>
+	</parameter>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="dataList" class="java.util.List"/>
+	<field name="attribTypes" class="java.util.List"/>
+	<field name="site" class="java.lang.Object"/>
+	<field name="section" class="java.lang.Object"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="57" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" x="398" y="14" width="340" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="14"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField>
+				<reportElement x="398" y="34" width="340" height="15" isPrintWhenDetailOverflows="true"/>
+				<textElement textAlignment="Center">
+					<font fontName="Serif" size="10"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Site: "+$F{site}.name+", "+"Section: "+$F{section}.name]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="492" splitType="Immediate">
+			<componentElement>
+				<reportElement key="table" style="table" x="2" y="2" width="820" height="488"/>
+				<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:column width="45">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="45" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<text><![CDATA[#]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:columnFooter height="2" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="45" height="2"/>
+								<textElement/>
+								<text><![CDATA[]]></text>
+							</staticText>
+						</jr:columnFooter>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField>
+								<reportElement x="2" y="0" width="41" height="36"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Asset Number}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="100">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="96" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Asset]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement positionType="Float" stretchType="RelativeToTallestObject" mode="Opaque" x="2" y="0" width="96" height="20" isPrintWhenDetailOverflows="true" backcolor="#D2EFF7"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="10" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+							</textField>
+							<textField isStretchWithOverflow="true">
+								<reportElement positionType="Float" stretchType="RelativeToTallestObject" x="2" y="20" width="96" height="15" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{description}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="90">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="86" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Comment]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="86" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{comment}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="55">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="51" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Serial Number]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="51" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Serial Number}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="60">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Model Number]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="36" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Model Number}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="65">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="2" y="0" width="61" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Manufacturer]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField>
+								<reportElement x="2" y="0" width="61" height="36"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Manufacturer}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="63">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="59" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Equipment Criticality (ecr)]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="63" height="36"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{ecr}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="50">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Risk Level]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Risk Level}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="60">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Safe Work Procedure]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Safe Work Procedure}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="50">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Regulatory Requirement (Y/N)]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Regulatory Requirement}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="60">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Maintenance % Completion]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Maintenance % Completion}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="60">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Registration Required (Y/N)]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Registration Required}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="50">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Registration Expiry Date]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Registration Expiry Date}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+				</jr:table>
+			</componentElement>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="28" splitType="Prevent">
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="704" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="784" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="28">
+			<textField evaluationTime="Report">
+				<reportElement x="784" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="704" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<textField>
+				<reportElement x="0" y="30" width="824" height="91"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Asset Extended Attributes: \n"+$F{attribTypes}]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="824" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="12" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="824" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="18"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/equipmentRegisterFinancial.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/equipmentRegisterFinancial.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/equipmentRegisterFinancial.jrxml	(revision 753)
@@ -0,0 +1,479 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="824" leftMargin="9" rightMargin="9" topMargin="9" bottomMargin="9" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true" isIgnorePagination="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.5"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="644"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="table" isDefault="false">
+		<pen lineWidth="0.5"/>
+		<box>
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="1.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="1.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#F0F8FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#BFE1FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" pattern="">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_GH" isDefault="false" mode="Opaque" backcolor="#D2EFF7"/>
+	<subDataset name="dataset1">
+		<queryString language="SQL">
+			<![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]>
+		</queryString>
+		<field name="name" class="java.lang.String"/>
+		<field name="description" class="java.lang.String"/>
+		<field name="comment" class="java.lang.String"/>
+		<field name="Serial Number" class="java.lang.String"/>
+		<field name="Model Number" class="java.lang.String"/>
+		<field name="Manufacturer" class="java.lang.String"/>
+		<field name="ecr" class="java.lang.String"/>
+		<field name="Risk Level" class="java.lang.String"/>
+		<field name="Safe Work Procedure" class="java.lang.String"/>
+		<field name="Regulatory Requirement" class="java.lang.String"/>
+		<field name="Maintenance % Completion" class="java.lang.String"/>
+		<field name="Registration Required" class="java.lang.String"/>
+		<field name="Registration Expiry Date" class="java.lang.String"/>
+		<field name="assetName" class="java.lang.String"/>
+		<field name="Asset Number" class="java.lang.String"/>
+		<field name="Location Description" class="java.lang.String"/>
+		<field name="Asset Condition" class="java.lang.String"/>
+		<group name="assetName">
+			<groupExpression><![CDATA[$F{assetName}]]></groupExpression>
+		</group>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
+		<defaultValueExpression><![CDATA["C:\\Documents and Settings\\kromhoutg\\My Documents\\reports\\"]]></defaultValueExpression>
+	</parameter>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="dataList" class="java.util.List"/>
+	<field name="attribTypes" class="java.lang.String"/>
+	<field name="assetsWithoutEquipment" class="java.lang.String"/>
+	<field name="site" class="java.lang.Object"/>
+	<field name="section" class="java.lang.Object"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="57" splitType="Stretch">
+			<printWhenExpression><![CDATA[false]]></printWhenExpression>
+			<textField>
+				<reportElement key="staticText-1" x="398" y="14" width="340" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="14"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField>
+				<reportElement x="398" y="34" width="340" height="15" isPrintWhenDetailOverflows="true"/>
+				<textElement textAlignment="Center">
+					<font fontName="Serif" size="10"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Site: "+$F{site}.name+", "+"Section: "+$F{section}.name]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="492" splitType="Immediate">
+			<componentElement>
+				<reportElement key="table" style="table" x="0" y="0" width="824" height="492"/>
+				<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:column width="45">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="45" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="10"/>
+								</textElement>
+								<text><![CDATA[#]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:columnFooter height="2" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="45" height="2"/>
+								<textElement/>
+								<text><![CDATA[]]></text>
+							</staticText>
+						</jr:columnFooter>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="45" height="36"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Asset Number}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="100">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="100" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Asset]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement positionType="Float" mode="Transparent" x="0" y="0" width="100" height="36" isPrintWhenDetailOverflows="true" backcolor="#D2EFF7"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" isBold="false"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{assetName}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="90">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="90" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Description]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="90" height="36">
+									<printWhenExpression><![CDATA[$F{name}.equals('   Asset Details')]]></printWhenExpression>
+								</reportElement>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{description}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="100">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="100" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Sub Asset]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement positionType="Float" mode="Transparent" x="0" y="0" width="100" height="36" isPrintWhenDetailOverflows="true" backcolor="#D2EFF7">
+									<printWhenExpression><![CDATA[!$F{name}.equals('   Asset Details')]]></printWhenExpression>
+								</reportElement>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="70">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="70" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Serial Number]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="70" height="36" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Serial Number}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="60">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="60" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Model Number]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="60" height="36" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Model Number}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="75">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="75" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Manufacturer]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="75" height="36" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Manufacturer}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="63">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="63" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Location]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="63" height="36"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Location Description}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="70">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="70" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Equipment Criticality]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="70" height="36"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{ecr}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="60">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="60" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Condition]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="60" height="36"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Asset Condition}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+				</jr:table>
+			</componentElement>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="28" splitType="Prevent">
+			<printWhenExpression><![CDATA[false]]></printWhenExpression>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="704" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="784" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="28">
+			<printWhenExpression><![CDATA[false]]></printWhenExpression>
+			<textField evaluationTime="Report">
+				<reportElement x="784" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="704" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<printWhenExpression><![CDATA[false]]></printWhenExpression>
+			<textField isStretchWithOverflow="true">
+				<reportElement positionType="Float" stretchType="RelativeToTallestObject" x="13" y="36" width="824" height="36" isPrintWhenDetailOverflows="true"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["AssetSubItem Extended Attributes: \n"+$F{attribTypes}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="242" y="0" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Summary"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement positionType="Float" stretchType="RelativeToTallestObject" x="13" y="100" width="824" height="26" isPrintWhenDetailOverflows="true"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{assetsWithoutEquipment}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement positionType="Float" stretchType="RelativeToTallestObject" x="13" y="81" width="824" height="19" isPrintWhenDetailOverflows="true" forecolor="#000000">
+					<printWhenExpression><![CDATA[$F{assetsWithoutEquipment}]]></printWhenExpression>
+				</reportElement>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["The following assets have no sub assets (equipment):"]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="824" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="12" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="824" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="18"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/equipmentRegisterOhs.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/equipmentRegisterOhs.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/equipmentRegisterOhs.jrxml	(revision 753)
@@ -0,0 +1,560 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="824" leftMargin="9" rightMargin="9" topMargin="9" bottomMargin="9" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.5"/>
+	<property name="ireport.x" value="337"/>
+	<property name="ireport.y" value="0"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="table" isDefault="false">
+		<pen lineWidth="0.5"/>
+		<box>
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="1.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="1.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#F0F8FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#BFE1FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" pattern="">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_GH" isDefault="false" mode="Opaque" backcolor="#D2EFF7"/>
+	<subDataset name="dataset1">
+		<queryString language="SQL">
+			<![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]>
+		</queryString>
+		<field name="name" class="java.lang.String"/>
+		<field name="description" class="java.lang.String"/>
+		<field name="comment" class="java.lang.String"/>
+		<field name="Serial Number" class="java.lang.String"/>
+		<field name="Model Number" class="java.lang.String"/>
+		<field name="Manufacturer" class="java.lang.String"/>
+		<field name="ecr" class="java.lang.String"/>
+		<field name="Risk Level" class="java.lang.String"/>
+		<field name="Safe Work Procedure" class="java.lang.String"/>
+		<field name="Regulatory Requirement" class="java.lang.String"/>
+		<field name="Regulatory Task Completion" class="java.lang.String"/>
+		<field name="Registration Required" class="java.lang.String"/>
+		<field name="Registration Expiry Date" class="java.lang.String"/>
+		<field name="assetName" class="java.lang.String"/>
+		<field name="Asset Number" class="java.lang.String"/>
+		<group name="assetName">
+			<groupExpression><![CDATA[$F{assetName}]]></groupExpression>
+		</group>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
+		<defaultValueExpression><![CDATA["C:\\Documents and Settings\\kromhoutg\\My Documents\\reports\\"]]></defaultValueExpression>
+	</parameter>
+	<parameter name="startDateString" class="java.lang.String"/>
+	<parameter name="endDateString" class="java.lang.String"/>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="dataList" class="java.util.List"/>
+	<field name="attribTypes" class="java.lang.String"/>
+	<field name="assetsWithoutEquipment" class="java.lang.String"/>
+	<field name="site" class="java.lang.Object"/>
+	<field name="section" class="java.lang.Object"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="57" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" x="398" y="5" width="340" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="14"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField>
+				<reportElement x="398" y="25" width="340" height="15" isPrintWhenDetailOverflows="true"/>
+				<textElement textAlignment="Center">
+					<font fontName="Serif" size="10"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Site: "+$F{site}.name+", "+"Section: "+$F{section}.name]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="398" y="40" width="340" height="12"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{startDateString}+" to "+$P{endDateString}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="492" splitType="Immediate">
+			<componentElement>
+				<reportElement key="table" style="table" x="2" y="2" width="820" height="488"/>
+				<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:column width="45">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="45" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="10"/>
+								</textElement>
+								<text><![CDATA[#]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:columnFooter height="2" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="45" height="2"/>
+								<textElement/>
+								<text><![CDATA[]]></text>
+							</staticText>
+						</jr:columnFooter>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField>
+								<reportElement x="2" y="0" width="41" height="36"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Asset Number}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="100">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="100" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Asset]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement positionType="Float" mode="Opaque" x="2" y="0" width="96" height="18" isPrintWhenDetailOverflows="true" backcolor="#D2EFF7">
+									<printWhenExpression><![CDATA[$F{name}.equals('   Asset Details')]]></printWhenExpression>
+								</reportElement>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" isBold="false"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{assetName}]]></textFieldExpression>
+							</textField>
+							<textField isStretchWithOverflow="true">
+								<reportElement positionType="Float" x="2" y="18" width="96" height="18" isPrintWhenDetailOverflows="true">
+									<printWhenExpression><![CDATA[$F{name}.equals('   Asset Details')]]></printWhenExpression>
+								</reportElement>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{description}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="100">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="96" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<text><![CDATA[Sub Asset]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement positionType="Float" mode="Opaque" x="2" y="0" width="96" height="18" isPrintWhenDetailOverflows="true" backcolor="#D2EFF7">
+									<printWhenExpression><![CDATA[!$F{name}.equals('   Asset Details')]]></printWhenExpression>
+								</reportElement>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+							</textField>
+							<textField isStretchWithOverflow="true">
+								<reportElement positionType="Float" x="2" y="18" width="96" height="18" isPrintWhenDetailOverflows="true">
+									<printWhenExpression><![CDATA[!$F{name}.equals('   Asset Details')]]></printWhenExpression>
+								</reportElement>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{description}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="55">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="51" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Serial Number]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="51" height="36" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Serial Number}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="60">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Model Number]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Model Number}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="65">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="61" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Manufacturer]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="61" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Manufacturer}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="63">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="59" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Equipment Criticality (ecr)]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="59" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{ecr}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="50">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Risk Level]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Risk Level}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="60">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Safe Work Procedure]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Safe Work Procedure}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="50">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Regulatory Requirement]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Regulatory Requirement}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="60">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Regulatory Task Complete]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Regulatory Task Completion}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="60">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Registration Required (Y/N)]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="56" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Registration Required}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="50">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Registration Expiry Date]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="36" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="46" height="35" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{Registration Expiry Date}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+				</jr:table>
+			</componentElement>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="28" splitType="Prevent">
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="704" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="784" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="28">
+			<textField evaluationTime="Report">
+				<reportElement x="784" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="704" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<textField isStretchWithOverflow="true">
+				<reportElement positionType="Float" stretchType="RelativeToTallestObject" x="13" y="36" width="824" height="36" isPrintWhenDetailOverflows="true"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["AssetSubItem Extended Attributes: \n"+$F{attribTypes}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="242" y="0" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Summary"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement positionType="Float" stretchType="RelativeToTallestObject" x="13" y="100" width="824" height="26" isPrintWhenDetailOverflows="true"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{assetsWithoutEquipment}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement positionType="Float" stretchType="RelativeToTallestObject" x="13" y="81" width="824" height="19" isPrintWhenDetailOverflows="true" forecolor="#000000">
+					<printWhenExpression><![CDATA[$F{assetsWithoutEquipment}]]></printWhenExpression>
+				</reportElement>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["The following assets have no sub assets (equipment):"]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="824" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="12" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="824" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="18"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/immediateCallouts.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/immediateCallouts.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/immediateCallouts.jrxml	(revision 753)
@@ -0,0 +1,368 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="782" leftMargin="30" rightMargin="30" topMargin="20" bottomMargin="20" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="1109"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="Crosstab Data Text" isDefault="false" hAlign="Center"/>
+	<style name="table" isDefault="false" fill="Solid" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="0.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="0.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#C7C7C7" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+		<conditionalStyle>
+			<conditionExpression><![CDATA[new Boolean($V{REPORT_COUNT}.intValue()%2==0)]]></conditionExpression>
+			<style isDefault="false" style="table_TD" backcolor="#F7F7F7"/>
+		</conditionalStyle>
+	</style>
+	<style name="table_CF" isDefault="false" mode="Opaque" backcolor="#EDEDED" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<subDataset name="dataset1">
+		<field name="id" class="java.lang.Long"/>
+		<field name="name" class="java.lang.String"/>
+		<field name="immediateCalloutCount" class="java.lang.Integer"/>
+		<field name="downTime" class="java.lang.Integer"/>
+		<field name="tasks" class="java.lang.String"/>
+		<variable name="immediateCalloutSum" class="java.lang.Integer" calculation="Sum">
+			<variableExpression><![CDATA[$F{immediateCalloutCount}]]></variableExpression>
+		</variable>
+		<variable name="downTimeSum" class="java.lang.Integer" calculation="Sum">
+			<variableExpression><![CDATA[$F{downTime}]]></variableExpression>
+		</variable>
+		<group name="assetName">
+			<groupExpression><![CDATA[$F{name}]]></groupExpression>
+		</group>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="startDateString" class="java.lang.String"/>
+	<parameter name="endDateString" class="java.lang.String"/>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="taskList" class="java.util.List"/>
+	<field name="summaryOfCalculationMethod" class="java.lang.String"/>
+	<field name="totalAssetsOnTasksCount" class="java.lang.String"/>
+	<field name="assetList" class="java.util.List"/>
+	<field name="totalDownTime" class="java.util.LinkedHashMap"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="121" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" x="0" y="57" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="0" y="87" width="340" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{startDateString}+" to "+$P{endDateString}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="394" splitType="Stretch">
+			<bar3DChart>
+				<chart>
+					<reportElement x="0" y="0" width="782" height="394"/>
+					<chartTitle position="Bottom">
+						<font isUnderline="false"/>
+						<titleExpression><![CDATA["Total: "+$F{totalAssetsOnTasksCount}]]></titleExpression>
+					</chartTitle>
+					<chartSubtitle/>
+					<chartLegend/>
+				</chart>
+				<categoryDataset>
+					<dataset>
+						<datasetRun subDataset="dataset1">
+							<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{assetList})]]></dataSourceExpression>
+						</datasetRun>
+					</dataset>
+					<categorySeries>
+						<seriesExpression><![CDATA["Immediate Callouts"]]></seriesExpression>
+						<categoryExpression><![CDATA[$F{name}]]></categoryExpression>
+						<valueExpression><![CDATA[$F{immediateCalloutCount}]]></valueExpression>
+					</categorySeries>
+				</categoryDataset>
+				<bar3DPlot isShowLabels="true">
+					<plot labelRotation="-60.0"/>
+					<itemLabel color="#000000" backgroundColor="#FFFFFF"/>
+					<categoryAxisFormat labelRotation="-60.0">
+						<axisFormat>
+							<labelFont/>
+							<tickLabelFont/>
+						</axisFormat>
+					</categoryAxisFormat>
+					<valueAxisFormat>
+						<axisFormat>
+							<labelFont/>
+							<tickLabelFont/>
+						</axisFormat>
+					</valueAxisFormat>
+				</bar3DPlot>
+			</bar3DChart>
+		</band>
+		<band height="394">
+			<bar3DChart>
+				<chart>
+					<reportElement x="0" y="0" width="782" height="394"/>
+					<chartTitle position="Bottom">
+						<font isBold="false" isUnderline="false"/>
+						<titleExpression><![CDATA["Total: "+$F{totalDownTime}.total+"min"+" ("+$F{totalDownTime}.hours+"h:"+$F{totalDownTime}.minutes+"m)"]]></titleExpression>
+					</chartTitle>
+					<chartSubtitle/>
+					<chartLegend position="Bottom">
+						<font isUnderline="true"/>
+					</chartLegend>
+				</chart>
+				<categoryDataset>
+					<dataset>
+						<datasetRun subDataset="dataset1">
+							<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{assetList})]]></dataSourceExpression>
+						</datasetRun>
+					</dataset>
+					<categorySeries>
+						<seriesExpression><![CDATA["Down Time (min)"]]></seriesExpression>
+						<categoryExpression><![CDATA[$F{name}]]></categoryExpression>
+						<valueExpression><![CDATA[$F{downTime}]]></valueExpression>
+					</categorySeries>
+				</categoryDataset>
+				<bar3DPlot isShowLabels="true">
+					<plot labelRotation="-60.0">
+						<seriesColor seriesOrder="0" color="#FF9900"/>
+					</plot>
+					<itemLabel color="#000000" backgroundColor="#FFFFFF"/>
+					<categoryAxisFormat labelRotation="-60.0">
+						<axisFormat>
+							<labelFont/>
+							<tickLabelFont/>
+						</axisFormat>
+					</categoryAxisFormat>
+					<valueAxisFormat>
+						<axisFormat>
+							<labelFont/>
+							<tickLabelFont/>
+						</axisFormat>
+					</valueAxisFormat>
+				</bar3DPlot>
+			</bar3DChart>
+		</band>
+		<band height="394">
+			<componentElement>
+				<reportElement key="table 1" style="table" x="0" y="0" width="782" height="394"/>
+				<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{assetList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:column width="774">
+						<jr:groupHeader groupName="assetName">
+							<jr:cell height="30" rowSpan="1">
+								<textField>
+									<reportElement x="0" y="0" width="774" height="30"/>
+									<textElement verticalAlignment="Middle">
+										<font size="12" isBold="true"/>
+									</textElement>
+									<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+								</textField>
+							</jr:cell>
+						</jr:groupHeader>
+						<jr:detailCell style="table_TD" height="40" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement x="0" y="0" width="774" height="40"/>
+								<textElement verticalAlignment="Middle"/>
+								<textFieldExpression class="java.lang.String"><![CDATA[""+$F{tasks}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+				</jr:table>
+			</componentElement>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="40" splitType="Stretch">
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="20" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="20" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="20" width="200" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="20" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="40">
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="20" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="20" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="20" width="200" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="20" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<textField>
+				<reportElement key="staticText-1" x="221" y="12" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Summary of Calculation Method"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="50" width="782" height="311"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{summaryOfCalculationMethod}]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="782" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="14" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="782" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/inventoryValueDetailed.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/inventoryValueDetailed.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/inventoryValueDetailed.jrxml	(revision 753)
@@ -0,0 +1,504 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="782" leftMargin="30" rightMargin="30" topMargin="12" bottomMargin="12" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="0"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="Crosstab Data Text" isDefault="false" hAlign="Center"/>
+	<style name="table" isDefault="false" fill="Solid" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="0.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="0.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#C7C7C7" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+		<conditionalStyle>
+			<conditionExpression><![CDATA[new Boolean($V{REPORT_COUNT}.intValue()%2==0)]]></conditionExpression>
+			<style isDefault="false" style="table_TD" backcolor="#F7F7F7"/>
+		</conditionalStyle>
+	</style>
+	<style name="table_CF" isDefault="false" mode="Opaque" backcolor="#EDEDED" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="horizontalBorder" isDefault="false">
+		<box>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="0.5"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<subDataset name="dataset1">
+		<field name="name" class="java.lang.String"/>
+		<field name="unitsInStock" class="java.lang.Integer"/>
+		<field name="inventoryLocation" class="java.lang.Object"/>
+		<field name="unitOfMeasure" class="java.lang.Object"/>
+		<field name="description" class="java.lang.String"/>
+		<field name="estimatedUnitPriceAmount" class="java.math.BigDecimal"/>
+		<field name="estimatedUnitPriceCurrency" class="java.lang.String"/>
+		<variable name="totalValue" class="java.math.BigDecimal" calculation="Sum">
+			<variableExpression><![CDATA[$F{estimatedUnitPriceAmount}]]></variableExpression>
+		</variable>
+	</subDataset>
+	<subDataset name="dataset2_inventoryTypes">
+		<field name="name" class="java.lang.String"/>
+	</subDataset>
+	<subDataset name="dataset3_inventoryGroups">
+		<field name="name" class="java.lang.String"/>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="inventoryItemList" class="java.util.List"/>
+	<field name="summaryOfCalculationMethod" class="java.lang.String"/>
+	<field name="inventoryItemCount" class="java.lang.Integer"/>
+	<field name="errorMessage" class="java.lang.String"/>
+	<field name="inventoryItemTotalValue" class="java.math.BigDecimal"/>
+	<field name="currency" class="java.lang.String"/>
+	<field name="inventoryTypes" class="java.util.List"/>
+	<field name="site" class="java.lang.Object"/>
+	<field name="inventoryGroups" class="java.util.List"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="54" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" mode="Transparent" x="400" y="6" width="350" height="20" backcolor="#FFFFFF"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="14"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="50"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField>
+				<reportElement x="400" y="26" width="350" height="18"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Site: "+$F{site}.name]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="438" splitType="Stretch">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement x="0" y="27" width="105" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total Value("+$F{currency}+"): "]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="# ##0" isBlankWhenNull="true">
+				<reportElement x="105" y="44" width="235" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.Integer"><![CDATA[$F{inventoryItemCount}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="#,##0.00" isBlankWhenNull="true">
+				<reportElement x="105" y="27" width="235" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{inventoryItemTotalValue}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement x="0" y="44" width="105" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Inventory Items: "]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement x="0" y="105" width="340" height="31"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{summaryOfCalculationMethod}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement mode="Opaque" x="0" y="72" width="340" height="29" forecolor="#FF0000" backcolor="#FFCCCC">
+					<printWhenExpression><![CDATA[$F{errorMessage} != null ? true:false]]></printWhenExpression>
+				</reportElement>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{errorMessage}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="horizontalBorder" x="175" y="173" width="160" height="17"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Inventory Types"]]></textFieldExpression>
+			</textField>
+			<componentElement>
+				<reportElement stretchType="RelativeToTallestObject" x="175" y="190" width="160" height="17" isPrintWhenDetailOverflows="true"/>
+				<jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" printOrder="Vertical">
+					<datasetRun subDataset="dataset2_inventoryTypes">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{inventoryTypes})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:listContents height="17" width="160">
+						<textField>
+							<reportElement style="horizontalBorder" x="0" y="0" width="160" height="17"/>
+							<textElement verticalAlignment="Middle">
+								<font fontName="Serif"/>
+							</textElement>
+							<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+						</textField>
+					</jr:listContents>
+				</jr:list>
+			</componentElement>
+			<textField>
+				<reportElement style="horizontalBorder" x="0" y="173" width="160" height="17"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Inventory Groups"]]></textFieldExpression>
+			</textField>
+			<componentElement>
+				<reportElement stretchType="RelativeToTallestObject" x="0" y="190" width="160" height="17" isPrintWhenDetailOverflows="true"/>
+				<jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" printOrder="Vertical">
+					<datasetRun subDataset="dataset3_inventoryGroups">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{inventoryGroups})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:listContents height="17" width="160">
+						<textField>
+							<reportElement style="horizontalBorder" x="0" y="0" width="160" height="17"/>
+							<textElement verticalAlignment="Middle">
+								<font fontName="Serif"/>
+							</textElement>
+							<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+						</textField>
+					</jr:listContents>
+				</jr:list>
+			</componentElement>
+			<textField isStretchWithOverflow="true">
+				<reportElement x="0" y="147" width="335" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isUnderline="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Included:"]]></textFieldExpression>
+			</textField>
+		</band>
+		<band height="489">
+			<componentElement>
+				<reportElement key="table 1" x="0" y="0" width="782" height="438"/>
+				<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{inventoryItemList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:column width="127">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="117" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif" size="10" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Inventory Item"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="24" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="2" width="117" height="20"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="237">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="237" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif" size="10" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Description"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="24" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="2" width="237" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{description}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="90">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="90" height="20"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" isBold="true"/>
+								</textElement>
+								<text><![CDATA[Location]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="24" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="2" width="90" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{inventoryLocation}.name+ " in "+$F{inventoryLocation}.inventoryStore.name]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="104">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="104" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="10" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["In Stock"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="24" rowSpan="1">
+							<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+								<leftPen lineWidth="0.0"/>
+								<rightPen lineWidth="0.0"/>
+							</box>
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="2" width="104" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{unitsInStock}+" "+$F{unitOfMeasure}.name]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="90">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="90" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="10" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Unit Price"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="24" rowSpan="1">
+							<textField isStretchWithOverflow="true" pattern="# ##0.00">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="2" width="90" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{estimatedUnitPriceAmount}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="82">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="82" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="10" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Total"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="24" rowSpan="1">
+							<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+								<leftPen lineWidth="0.0"/>
+								<rightPen lineWidth="0.0"/>
+							</box>
+							<textField isStretchWithOverflow="true" pattern="# ##0.00">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="2" width="82" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{estimatedUnitPriceAmount}.multiply( $F{unitsInStock} )]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="52">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="51" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif" size="10" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Currency"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="24" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="2" width="51" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{estimatedUnitPriceCurrency}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+				</jr:table>
+			</componentElement>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="28" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="28">
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="782" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="14" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="782" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/inventoryValueOverview.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/inventoryValueOverview.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/inventoryValueOverview.jrxml	(revision 753)
@@ -0,0 +1,399 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="782" leftMargin="30" rightMargin="30" topMargin="12" bottomMargin="12" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="0"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="Crosstab Data Text" isDefault="false" hAlign="Center"/>
+	<style name="table" isDefault="false" fill="Solid" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="0.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="0.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#C7C7C7" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+		<conditionalStyle>
+			<conditionExpression><![CDATA[new Boolean($V{REPORT_COUNT}.intValue()%2==0)]]></conditionExpression>
+			<style isDefault="false" style="table_TD" backcolor="#F7F7F7"/>
+		</conditionalStyle>
+	</style>
+	<style name="table_CF" isDefault="false" mode="Opaque" backcolor="#EDEDED" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="horizontalBorder" isDefault="false">
+		<box>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="0.5"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<subDataset name="dataset2_inventoryTypes">
+		<field name="name" class="java.lang.String"/>
+		<field name="value" class="java.math.BigDecimal"/>
+	</subDataset>
+	<subDataset name="dataset3_inventoryGroups">
+		<field name="name" class="java.lang.String"/>
+		<field name="value" class="java.math.BigDecimal"/>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="summaryOfCalculationMethod" class="java.lang.String"/>
+	<field name="inventoryItemCount" class="java.lang.Integer"/>
+	<field name="errorMessage" class="java.lang.String"/>
+	<field name="inventoryItemTotalValue" class="java.math.BigDecimal"/>
+	<field name="currency" class="java.lang.String"/>
+	<field name="inventoryTypes" class="java.util.List"/>
+	<field name="inventoryGroups" class="java.util.List"/>
+	<field name="site" class="java.lang.Object"/>
+	<field name="groups" class="java.util.List"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="54" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" mode="Transparent" x="400" y="6" width="350" height="20" backcolor="#FFFFFF"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="14"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="50"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField>
+				<reportElement x="400" y="26" width="350" height="18"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Site: "+$F{site}.name]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="438" splitType="Stretch">
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement x="0" y="27" width="105" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total Value("+$F{currency}+"): "]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="# ##0" isBlankWhenNull="true">
+				<reportElement x="105" y="44" width="235" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.Integer"><![CDATA[$F{inventoryItemCount}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="#,##0.00" isBlankWhenNull="true">
+				<reportElement x="105" y="27" width="235" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{inventoryItemTotalValue}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement x="0" y="44" width="105" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Inventory Items: "]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement x="0" y="105" width="340" height="31"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{summaryOfCalculationMethod}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement mode="Opaque" x="0" y="72" width="340" height="29" forecolor="#FF0000" backcolor="#FFCCCC">
+					<printWhenExpression><![CDATA[$F{errorMessage} != null ? true:false]]></printWhenExpression>
+				</reportElement>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{errorMessage}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="horizontalBorder" x="400" y="148" width="335" height="17"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Inventory Types"]]></textFieldExpression>
+			</textField>
+			<componentElement>
+				<reportElement stretchType="RelativeToTallestObject" x="400" y="199" width="335" height="17" isPrintWhenDetailOverflows="true"/>
+				<jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" printOrder="Vertical">
+					<datasetRun subDataset="dataset2_inventoryTypes">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{inventoryTypes})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:listContents height="17" width="335">
+						<textField>
+							<reportElement style="horizontalBorder" x="0" y="0" width="235" height="17"/>
+							<textElement verticalAlignment="Middle">
+								<font fontName="Serif"/>
+							</textElement>
+							<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+						</textField>
+						<textField pattern="#,##0.00">
+							<reportElement style="horizontalBorder" x="235" y="0" width="100" height="17"/>
+							<textElement verticalAlignment="Middle">
+								<font fontName="Serif"/>
+							</textElement>
+							<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{value}]]></textFieldExpression>
+						</textField>
+					</jr:listContents>
+				</jr:list>
+			</componentElement>
+			<textField>
+				<reportElement style="horizontalBorder" x="0" y="148" width="335" height="17"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Inventory Groups"]]></textFieldExpression>
+			</textField>
+			<componentElement>
+				<reportElement stretchType="RelativeToTallestObject" x="0" y="199" width="335" height="17" isPrintWhenDetailOverflows="true"/>
+				<jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" printOrder="Vertical">
+					<datasetRun subDataset="dataset3_inventoryGroups">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{inventoryGroups})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:listContents height="17" width="335">
+						<textField>
+							<reportElement style="horizontalBorder" x="0" y="0" width="235" height="17"/>
+							<textElement verticalAlignment="Middle">
+								<font fontName="Serif"/>
+							</textElement>
+							<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+						</textField>
+						<textField pattern="#,##0.00">
+							<reportElement style="horizontalBorder" x="235" y="0" width="100" height="17"/>
+							<textElement verticalAlignment="Middle">
+								<font fontName="Serif"/>
+							</textElement>
+							<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{value}]]></textFieldExpression>
+						</textField>
+					</jr:listContents>
+				</jr:list>
+			</componentElement>
+			<textField>
+				<reportElement style="horizontalBorder" x="0" y="165" width="235" height="17"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Name"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="horizontalBorder" x="235" y="165" width="100" height="17"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Value("+$F{currency}+")"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="horizontalBorder" x="635" y="165" width="100" height="17"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Value("+$F{currency}+")"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement style="horizontalBorder" x="400" y="165" width="235" height="17"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Name"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="horizontalBorder" x="0" y="182" width="235" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="10" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total Value:"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="#,##0.00" isBlankWhenNull="true">
+				<reportElement style="horizontalBorder" x="235" y="182" width="100" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="10" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{inventoryItemTotalValue}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" isBlankWhenNull="true">
+				<reportElement style="horizontalBorder" x="400" y="182" width="235" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="10" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total Value:"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="#,##0.00" isBlankWhenNull="true">
+				<reportElement style="horizontalBorder" x="635" y="182" width="100" height="17" isPrintWhenDetailOverflows="true"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="10" isBold="false"/>
+				</textElement>
+				<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{inventoryItemTotalValue}]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="28" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="28">
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="782" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="14" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="782" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/mandatoryRequirements.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/mandatoryRequirements.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/mandatoryRequirements.jrxml	(revision 753)
@@ -0,0 +1,335 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="824" leftMargin="9" rightMargin="9" topMargin="9" bottomMargin="9" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.5"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="665"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="table" isDefault="false">
+		<pen lineWidth="0.5"/>
+		<box>
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="1.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="1.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#F0F8FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#BFE1FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" pattern="">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_GH" isDefault="false" mode="Opaque" backcolor="#D2EFF7"/>
+	<subDataset name="dataset1">
+		<queryString language="SQL">
+			<![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]>
+		</queryString>
+		<field name="assetDescription" class="java.lang.String"/>
+		<field name="taskDescription" class="java.lang.String"/>
+		<field name="assetName" class="java.lang.String"/>
+		<field name="completionFigures" class="java.lang.String"/>
+		<field name="taskId" class="java.lang.String"/>
+		<group name="group1">
+			<groupExpression><![CDATA[$F{assetName}]]></groupExpression>
+		</group>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
+		<defaultValueExpression><![CDATA["C:\\Documents and Settings\\kromhoutg\\My Documents\\reports\\"]]></defaultValueExpression>
+	</parameter>
+	<parameter name="startDateString" class="java.lang.String"/>
+	<parameter name="endDateString" class="java.lang.String"/>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="dataList" class="java.util.List"/>
+	<field name="site" class="java.lang.Object"/>
+	<field name="section" class="java.lang.Object"/>
+	<field name="summary" class="java.lang.String"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="57" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" x="398" y="5" width="340" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="14"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField>
+				<reportElement x="398" y="25" width="340" height="15" isPrintWhenDetailOverflows="true"/>
+				<textElement textAlignment="Center">
+					<font fontName="Serif" size="10"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Site: "+$F{site}.name+", "+"Section: "+$F{section}.name]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="398" y="40" width="340" height="12"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{startDateString}+" to "+$P{endDateString}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="492" splitType="Immediate">
+			<printWhenExpression><![CDATA[!$F{dataList}.isEmpty()]]></printWhenExpression>
+			<componentElement>
+				<reportElement key="table" style="table" x="2" y="2" width="820" height="488"/>
+				<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:column width="100">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="100" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Asset]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" mode="Transparent" x="2" y="0" width="96" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{assetName}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="100">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="100" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<text><![CDATA[Description]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" mode="Transparent" x="2" y="0" width="96" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{assetDescription}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="441">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="435" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="10" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Mandatory Requirement (Recurring Task)]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" mode="Transparent" x="2" y="0" width="435" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Task #"+$F{taskId}+" - "+$F{taskDescription}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="112">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="2" y="0" width="108" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<text><![CDATA[Complete (Sub Tasks)]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" mode="Transparent" x="2" y="0" width="108" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{completionFigures}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+				</jr:table>
+			</componentElement>
+		</band>
+		<band height="85">
+			<printWhenExpression><![CDATA[$F{dataList}.isEmpty()]]></printWhenExpression>
+			<staticText>
+				<reportElement x="0" y="35" width="824" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="12" isBold="true"/>
+				</textElement>
+				<text><![CDATA[No mandatory requirements found for this section.]]></text>
+			</staticText>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="28" splitType="Prevent">
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="704" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="784" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="28">
+			<textField evaluationTime="Report">
+				<reportElement x="784" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="704" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<textField>
+				<reportElement key="staticText-1" x="242" y="0" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Summary"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="2" y="63" width="555" height="48"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{summary}]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="824" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="12" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="824" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="18"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/reactiveRatio.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/reactiveRatio.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/reactiveRatio.jrxml	(revision 753)
@@ -0,0 +1,809 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="782" leftMargin="30" rightMargin="30" topMargin="20" bottomMargin="20" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="2.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="170"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="table" isDefault="false">
+		<box>
+			<pen lineWidth="1.0" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#F0F8FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#BFE1FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table 1" isDefault="false">
+		<box>
+			<pen lineWidth="1.0" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table 1_TH" isDefault="false" mode="Opaque" backcolor="#F0F8FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table 1_CH" isDefault="false" mode="Opaque" backcolor="#BFE1FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table 1_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="Crosstab Data Text" isDefault="false" hAlign="Center"/>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="startDateString" class="java.lang.String"/>
+	<parameter name="endDateString" class="java.lang.String"/>
+	<field name="immediateCalloutPercentage" class="java.math.BigDecimal"/>
+	<field name="totalPreventativePercentage" class="java.math.BigDecimal"/>
+	<field name="immediateCalloutCount" class="java.lang.Integer"/>
+	<field name="totalAssetsOnTasksCount" class="java.lang.Integer"/>
+	<field name="totalPreventativeCount" class="java.lang.Integer"/>
+	<field name="unscheduledBreakinCount" class="java.lang.Integer"/>
+	<field name="preventativeMaintenanceCount" class="java.lang.Integer"/>
+	<field name="taskQuery" class="java.lang.String"/>
+	<field name="summaryOfCalculationMethod" class="java.lang.String"/>
+	<field name="immediateCalloutWorkDone" class="java.util.LinkedHashMap"/>
+	<field name="totalPreventativeWorkDone" class="java.util.LinkedHashMap"/>
+	<field name="unscheduledBreakinWorkDone" class="java.util.LinkedHashMap"/>
+	<field name="preventativeMaintenanceWorkDone" class="java.util.LinkedHashMap"/>
+	<field name="totalWorkDone" class="java.util.LinkedHashMap"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="121" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" x="0" y="57" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="0" y="87" width="340" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{startDateString}+" to "+$P{endDateString}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="394" splitType="Stretch">
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="40" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Immediate Callout: "]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="60" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total Preventative: "]]></textFieldExpression>
+			</textField>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="40" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{immediateCalloutPercentage}.setScale(2, RoundingMode.HALF_UP)]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="157" y="60" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{totalPreventativePercentage}.setScale(2, RoundingMode.HALF_UP)]]></textFieldExpression>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="0" y="80" width="157" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total: "]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="157" y="80" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<line>
+				<reportElement x="0" y="100" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<line>
+				<reportElement x="0" y="79" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<line>
+				<reportElement x="0" y="60" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<line>
+				<reportElement x="0" y="39" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="20" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none"/>
+			</textField>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="20" width="79" height="20"/>
+				<textElement verticalAlignment="Middle"/>
+			</textField>
+			<line>
+				<reportElement x="0" y="20" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<pie3DChart>
+				<chart theme="default">
+					<reportElement x="426" y="0" width="356" height="197"/>
+					<chartTitle/>
+					<chartSubtitle/>
+					<chartLegend/>
+				</chart>
+				<pieDataset>
+					<pieSeries>
+						<keyExpression><![CDATA["Immediate"]]></keyExpression>
+						<valueExpression><![CDATA[$F{immediateCalloutPercentage}]]></valueExpression>
+						<labelExpression><![CDATA[$F{immediateCalloutPercentage}.setScale(2, RoundingMode.HALF_UP)]]></labelExpression>
+					</pieSeries>
+					<pieSeries>
+						<keyExpression><![CDATA["Preventative"]]></keyExpression>
+						<valueExpression><![CDATA[$F{totalPreventativePercentage}]]></valueExpression>
+						<labelExpression><![CDATA[$F{totalPreventativePercentage}.setScale(2, RoundingMode.HALF_UP)]]></labelExpression>
+					</pieSeries>
+				</pieDataset>
+				<pie3DPlot depthFactor="0.1" isCircular="false">
+					<plot>
+						<seriesColor seriesOrder="0" color="#FF0000"/>
+						<seriesColor seriesOrder="1" color="#00CC00"/>
+						<seriesColor seriesOrder="2" color="#FF9900"/>
+					</plot>
+					<itemLabel color="#000000" backgroundColor="#FFFFFF"/>
+				</pie3DPlot>
+			</pie3DChart>
+			<textField isBlankWhenNull="true">
+				<reportElement x="236" y="257" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle"/>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{preventativeMaintenanceCount}]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="236" y="277" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{totalPreventativeCount}]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="157" y="277" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<line>
+				<reportElement x="0" y="297" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="257" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Preventative Maintenance: "]]></textFieldExpression>
+			</textField>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="237" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="217" width="130" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<line>
+				<reportElement x="0" y="257" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="197" width="130" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Count (Assets on Tasks)"]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="237" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Unscheduled Breakin: "]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement x="0" y="276" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<pie3DChart>
+				<chart>
+					<reportElement x="426" y="197" width="356" height="197"/>
+					<chartTitle/>
+					<chartSubtitle/>
+					<chartLegend/>
+				</chart>
+				<pieDataset>
+					<pieSeries>
+						<keyExpression><![CDATA["Immediate"]]></keyExpression>
+						<valueExpression><![CDATA[$F{immediateCalloutCount}]]></valueExpression>
+						<labelExpression><![CDATA[$F{immediateCalloutCount}]]></labelExpression>
+					</pieSeries>
+					<pieSeries>
+						<keyExpression><![CDATA["Preventative Maintenance"]]></keyExpression>
+						<valueExpression><![CDATA[$F{preventativeMaintenanceCount}]]></valueExpression>
+						<labelExpression><![CDATA[$F{preventativeMaintenanceCount}]]></labelExpression>
+					</pieSeries>
+					<pieSeries>
+						<keyExpression><![CDATA["Unscheduled Breakin"]]></keyExpression>
+						<valueExpression><![CDATA[$F{unscheduledBreakinCount}]]></valueExpression>
+						<labelExpression><![CDATA[$F{unscheduledBreakinCount}]]></labelExpression>
+					</pieSeries>
+				</pieDataset>
+				<pie3DPlot depthFactor="0.1" isCircular="false">
+					<plot>
+						<seriesColor seriesOrder="0" color="#FF0000"/>
+						<seriesColor seriesOrder="1" color="#00CC00"/>
+						<seriesColor seriesOrder="2" color="#FF9900"/>
+					</plot>
+					<itemLabel color="#000000" backgroundColor="#FFFFFF"/>
+				</pie3DPlot>
+			</pie3DChart>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="217" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="237" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{unscheduledBreakinCount}]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement x="0" y="217" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="217" width="79" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<line>
+				<reportElement x="0" y="236" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField isBlankWhenNull="true">
+				<reportElement x="157" y="257" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="197" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Description"]]></textFieldExpression>
+			</textField>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="197" width="79" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="0" y="277" width="157" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total Preventative: "]]></textFieldExpression>
+			</textField>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="0" width="79" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Percentage (%)"]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="0" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Description"]]></textFieldExpression>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="40" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{immediateCalloutCount}]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="236" y="60" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{totalPreventativeCount}]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="236" y="80" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{totalAssetsOnTasksCount}]]></textFieldExpression>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="20" width="130" height="20"/>
+				<textElement verticalAlignment="Middle"/>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="0" width="130" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Count (Assets on Tasks)"]]></textFieldExpression>
+			</textField>
+		</band>
+		<band height="394">
+			<pie3DChart>
+				<chart>
+					<reportElement x="426" y="0" width="356" height="197"/>
+					<chartTitle/>
+					<chartSubtitle/>
+					<chartLegend/>
+				</chart>
+				<pieDataset>
+					<pieSeries>
+						<keyExpression><![CDATA["Immediate"]]></keyExpression>
+						<valueExpression><![CDATA[$F{immediateCalloutWorkDone}.percentage]]></valueExpression>
+						<labelExpression><![CDATA[$F{immediateCalloutWorkDone}.percentage.setScale(2, RoundingMode.HALF_UP)]]></labelExpression>
+					</pieSeries>
+					<pieSeries>
+						<keyExpression><![CDATA["Total Preventative"]]></keyExpression>
+						<valueExpression><![CDATA[$F{totalPreventativeWorkDone}.percentage]]></valueExpression>
+						<labelExpression><![CDATA[$F{totalPreventativeWorkDone}.percentage.setScale(2, RoundingMode.HALF_UP)]]></labelExpression>
+					</pieSeries>
+				</pieDataset>
+				<pie3DPlot depthFactor="0.1" isCircular="false">
+					<plot>
+						<seriesColor seriesOrder="0" color="#FF0000"/>
+						<seriesColor seriesOrder="1" color="#00CC00"/>
+						<seriesColor seriesOrder="2" color="#FF9900"/>
+					</plot>
+					<itemLabel color="#000000" backgroundColor="#FFFFFF"/>
+				</pie3DPlot>
+			</pie3DChart>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="0" width="79" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Percentage (%)"]]></textFieldExpression>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="20" width="130" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="0" width="130" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Work Done (hh:mm)"]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement x="0" y="100" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<line>
+				<reportElement x="0" y="20" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="40" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{immediateCalloutWorkDone}.percentage.setScale(2, RoundingMode.HALF_UP)]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="157" y="60" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{totalPreventativeWorkDone}.percentage.setScale(2, RoundingMode.HALF_UP)]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="20" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="157" y="80" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<line>
+				<reportElement x="0" y="60" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField isBlankWhenNull="true">
+				<reportElement x="236" y="60" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{totalPreventativeWorkDone}.hours+":"+$F{totalPreventativeWorkDone}.minutes]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="236" y="80" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{totalWorkDone}.hours+":"+$F{totalWorkDone}.minutes]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="0" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Description"]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement x="0" y="79" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="40" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Immediate Callout: "]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="60" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total Preventative: "]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement x="0" y="39" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="20" width="79" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="0" y="80" width="157" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total: "]]></textFieldExpression>
+			</textField>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="236" y="40" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{immediateCalloutWorkDone}.hours+":"+$F{immediateCalloutWorkDone}.minutes]]></textFieldExpression>
+			</textField>
+			<pie3DChart>
+				<chart>
+					<reportElement x="426" y="197" width="356" height="197"/>
+					<chartTitle/>
+					<chartSubtitle/>
+					<chartLegend/>
+				</chart>
+				<pieDataset>
+					<pieSeries>
+						<keyExpression><![CDATA["Immediate"]]></keyExpression>
+						<valueExpression><![CDATA[$F{immediateCalloutWorkDone}.total]]></valueExpression>
+						<labelExpression><![CDATA[$F{immediateCalloutWorkDone}.hours+":"+$F{immediateCalloutWorkDone}.minutes]]></labelExpression>
+					</pieSeries>
+					<pieSeries>
+						<keyExpression><![CDATA["Preventative Maintenance"]]></keyExpression>
+						<valueExpression><![CDATA[$F{preventativeMaintenanceWorkDone}.total]]></valueExpression>
+						<labelExpression><![CDATA[$F{preventativeMaintenanceWorkDone}.hours+":"+$F{preventativeMaintenanceWorkDone}.minutes]]></labelExpression>
+					</pieSeries>
+					<pieSeries>
+						<keyExpression><![CDATA["Unscheduled Breakin"]]></keyExpression>
+						<valueExpression><![CDATA[$F{unscheduledBreakinWorkDone}.total]]></valueExpression>
+						<labelExpression><![CDATA[$F{unscheduledBreakinWorkDone}.hours+":"+$F{unscheduledBreakinWorkDone}.minutes]]></labelExpression>
+					</pieSeries>
+				</pieDataset>
+				<pie3DPlot depthFactor="0.1" isCircular="false">
+					<plot>
+						<seriesColor seriesOrder="0" color="#FF0000"/>
+						<seriesColor seriesOrder="1" color="#00CC00"/>
+						<seriesColor seriesOrder="2" color="#FF9900"/>
+					</plot>
+					<itemLabel color="#000000" backgroundColor="#FFFFFF"/>
+				</pie3DPlot>
+			</pie3DChart>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="197" width="79" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="197" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Description"]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement x="0" y="276" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="217" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="157" y="257" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="197" width="130" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Work Done (hh:mm)"]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="157" y="277" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="237" width="79" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField pattern="#,##0.00 %" isBlankWhenNull="true">
+				<reportElement x="157" y="217" width="79" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<line>
+				<reportElement x="0" y="257" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<line>
+				<reportElement x="0" y="297" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="0" y="277" width="157" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total Preventative: "]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="236" y="277" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{totalPreventativeWorkDone}.hours+":"+$F{totalPreventativeWorkDone}.minutes]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement x="0" y="236" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="217" width="130" height="20"/>
+				<textElement verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="237" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Unscheduled Breakin: "]]></textFieldExpression>
+			</textField>
+			<textField isBlankWhenNull="true">
+				<reportElement x="0" y="257" width="157" height="20"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Preventative Maintenance: "]]></textFieldExpression>
+			</textField>
+			<line>
+				<reportElement x="0" y="217" width="366" height="1" forecolor="#999999"/>
+			</line>
+			<textField isBlankWhenNull="true">
+				<reportElement x="236" y="257" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{preventativeMaintenanceWorkDone}.hours+":"+$F{preventativeMaintenanceWorkDone}.minutes]]></textFieldExpression>
+			</textField>
+			<textField pattern="###0.00" isBlankWhenNull="true">
+				<reportElement x="236" y="237" width="130" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{unscheduledBreakinWorkDone}.hours+":"+$F{unscheduledBreakinWorkDone}.minutes]]></textFieldExpression>
+			</textField>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="40" splitType="Stretch">
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="20" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="20" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="20" width="200" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="20" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="40">
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="20" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="20" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="20" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="20" width="200" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="277">
+			<textField>
+				<reportElement key="staticText-1" x="221" y="0" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Summary of Calculation Method"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="30" width="782" height="245"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{summaryOfCalculationMethod}]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="782" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="14" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="782" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/regulatoryRequirements.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/regulatoryRequirements.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/regulatoryRequirements.jrxml	(revision 753)
@@ -0,0 +1,335 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="824" leftMargin="9" rightMargin="9" topMargin="9" bottomMargin="9" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.5"/>
+	<property name="ireport.x" value="22"/>
+	<property name="ireport.y" value="480"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="table" isDefault="false">
+		<pen lineWidth="0.5"/>
+		<box>
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="1.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="1.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#F0F8FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#BFE1FF">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" pattern="">
+		<box>
+			<pen lineWidth="0.5" lineColor="#000000"/>
+		</box>
+	</style>
+	<style name="table_GH" isDefault="false" mode="Opaque" backcolor="#D2EFF7"/>
+	<subDataset name="dataset1">
+		<queryString language="SQL">
+			<![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]>
+		</queryString>
+		<field name="assetDescription" class="java.lang.String"/>
+		<field name="taskDescription" class="java.lang.String"/>
+		<field name="assetName" class="java.lang.String"/>
+		<field name="completionFigures" class="java.lang.String"/>
+		<field name="taskId" class="java.lang.String"/>
+		<group name="group1">
+			<groupExpression><![CDATA[$F{assetName}]]></groupExpression>
+		</group>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
+		<defaultValueExpression><![CDATA["C:\\Documents and Settings\\kromhoutg\\My Documents\\reports\\"]]></defaultValueExpression>
+	</parameter>
+	<parameter name="startDateString" class="java.lang.String"/>
+	<parameter name="endDateString" class="java.lang.String"/>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="dataList" class="java.util.List"/>
+	<field name="site" class="java.lang.Object"/>
+	<field name="section" class="java.lang.Object"/>
+	<field name="summary" class="java.lang.String"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="57" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" x="398" y="5" width="340" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="14"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField>
+				<reportElement x="398" y="25" width="340" height="15" isPrintWhenDetailOverflows="true"/>
+				<textElement textAlignment="Center">
+					<font fontName="Serif" size="10"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Site: "+$F{site}.name+", "+"Section: "+$F{section}.name]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="398" y="40" width="340" height="12"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{startDateString}+" to "+$P{endDateString}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="492" splitType="Immediate">
+			<printWhenExpression><![CDATA[!$F{dataList}.isEmpty()]]></printWhenExpression>
+			<componentElement>
+				<reportElement key="table" style="table" x="2" y="2" width="820" height="488"/>
+				<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:column width="100">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="100" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Asset]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" mode="Transparent" x="2" y="0" width="96" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{assetName}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="100">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="0" y="0" width="100" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<text><![CDATA[Description]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" mode="Transparent" x="2" y="0" width="96" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{assetDescription}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="441">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement stretchType="RelativeToTallestObject" x="2" y="0" width="435" height="32" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="10" isBold="false"/>
+								</textElement>
+								<text><![CDATA[Regulatory Requirement (Recurring Task)]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" mode="Transparent" x="2" y="0" width="435" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Task #"+$F{taskId}+" - "+$F{taskDescription}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="112">
+						<jr:columnHeader style="table_CH" height="32" rowSpan="1">
+							<staticText>
+								<reportElement x="2" y="0" width="108" height="32"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<text><![CDATA[Complete (Sub Tasks)]]></text>
+							</staticText>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement stretchType="RelativeToTallestObject" mode="Transparent" x="2" y="0" width="108" height="20" isPrintWhenDetailOverflows="true"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="8"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{completionFigures}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+				</jr:table>
+			</componentElement>
+		</band>
+		<band height="85">
+			<printWhenExpression><![CDATA[$F{dataList}.isEmpty()]]></printWhenExpression>
+			<staticText>
+				<reportElement x="0" y="35" width="824" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="12" isBold="true"/>
+				</textElement>
+				<text><![CDATA[No regulatory requirements found for this section.]]></text>
+			</staticText>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="28" splitType="Prevent">
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="704" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="784" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="28">
+			<textField evaluationTime="Report">
+				<reportElement x="784" y="14" width="40" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="50" y="2" width="200" height="12"/>
+				<textElement>
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="2" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="14" width="50" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="50" y="14" width="200" height="12"/>
+				<textElement markup="none">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="704" y="14" width="80" height="12"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif" size="8"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<textField>
+				<reportElement key="staticText-1" x="242" y="0" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Summary"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="2" y="63" width="555" height="48"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{summary}]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="824" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="12" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="824" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="18"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/stockTakeByLocation.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/stockTakeByLocation.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/stockTakeByLocation.jrxml	(revision 753)
@@ -0,0 +1,421 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="782" leftMargin="30" rightMargin="30" topMargin="12" bottomMargin="12" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="309"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="Crosstab Data Text" isDefault="false" hAlign="Center"/>
+	<style name="table" isDefault="false" fill="Solid" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="0.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="0.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#C7C7C7" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+		<conditionalStyle>
+			<conditionExpression><![CDATA[new Boolean($V{REPORT_COUNT}.intValue()%2==0)]]></conditionExpression>
+			<style isDefault="false" style="table_TD" backcolor="#F7F7F7"/>
+		</conditionalStyle>
+	</style>
+	<style name="table_CF" isDefault="false" mode="Opaque" backcolor="#EDEDED" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<subDataset name="dataset1">
+		<field name="name" class="java.lang.String"/>
+		<field name="unitsInStock" class="java.lang.Integer"/>
+		<field name="inventoryLocation" class="java.lang.Object"/>
+		<field name="picture" class="java.lang.Object"/>
+		<field name="unitOfMeasure" class="java.lang.Object"/>
+		<field name="description" class="java.lang.String"/>
+		<group name="group1">
+			<groupExpression><![CDATA[$F{inventoryLocation}.name]]></groupExpression>
+		</group>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="locationString" class="java.lang.String"/>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="inventoryItemList" class="java.util.List"/>
+	<field name="summaryOfCalculationMethod" class="java.lang.String"/>
+	<field name="inventoryItemCount" class="java.lang.Integer"/>
+	<field name="locations" class="java.lang.String"/>
+	<field name="errorMessage" class="java.lang.String"/>
+	<field name="locationCount" class="java.lang.Integer"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="93" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" mode="Transparent" x="0" y="50" width="340" height="26" backcolor="#FFFFFF"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="50"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField isStretchWithOverflow="true" pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="0" y="76" width="340" height="17"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total - Items: "+$F{inventoryItemCount}+", Locations: "+$F{locationCount}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement mode="Opaque" x="400" y="4" width="382" height="46" isPrintWhenDetailOverflows="true" forecolor="#FF0000" backcolor="#FFCCCC">
+					<printWhenExpression><![CDATA[$F{errorMessage} != null ? true:false]]></printWhenExpression>
+				</reportElement>
+				<textElement textAlignment="Center" verticalAlignment="Middle">
+					<font fontName="Serif" size="12" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{errorMessage}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="438" splitType="Stretch">
+			<componentElement>
+				<reportElement key="table 1" x="0" y="0" width="782" height="438"/>
+				<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{inventoryItemList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:column width="127">
+						<jr:groupHeader groupName="group1">
+							<jr:cell height="20" rowSpan="1">
+								<textField isStretchWithOverflow="true">
+									<reportElement x="0" y="0" width="117" height="20"/>
+									<textElement verticalAlignment="Middle">
+										<font fontName="Serif" size="12" isBold="true"/>
+									</textElement>
+									<textFieldExpression class="java.lang.String"><![CDATA[$F{inventoryLocation}.name+" in "+$F{inventoryLocation}.inventoryStore.name]]></textFieldExpression>
+								</textField>
+							</jr:cell>
+						</jr:groupHeader>
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement x="0" y="0" width="117" height="20"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{inventoryLocation}.name]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="51" rowSpan="1">
+							<image hAlign="Center" vAlign="Middle">
+								<reportElement x="29" y="0" width="88" height="51"/>
+								<imageExpression class="java.awt.Image"><![CDATA[net.sf.jasperreports.engine.util.JRImageLoader.loadImage($F{picture}.images.first().data)]]></imageExpression>
+							</image>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="237">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement x="0" y="0" width="237" height="20"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Inventory Item"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="51" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement x="0" y="0" width="237" height="25"/>
+								<textElement verticalAlignment="Top">
+									<font fontName="Serif"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
+							</textField>
+							<textField isStretchWithOverflow="true">
+								<reportElement x="0" y="25" width="237" height="25"/>
+								<textElement>
+									<font fontName="Serif"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{description}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="104">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement x="0" y="0" width="104" height="20"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["In Stock"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="51" rowSpan="1">
+							<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+								<leftPen lineWidth="0.0"/>
+								<rightPen lineWidth="0.0"/>
+							</box>
+							<textField isStretchWithOverflow="true">
+								<reportElement x="0" y="0" width="104" height="51"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{unitsInStock}+" "+$F{unitOfMeasure}.name]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="90">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement x="0" y="0" width="90" height="20"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Actual Stock"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="51" rowSpan="1">
+							<rectangle>
+								<reportElement x="5" y="11" width="80" height="30"/>
+							</rectangle>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="82">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement x="0" y="0" width="82" height="20"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Correction Required"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="51" rowSpan="1">
+							<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+								<leftPen lineWidth="0.0"/>
+								<rightPen lineWidth="0.0"/>
+							</box>
+							<rectangle radius="10">
+								<reportElement x="31" y="15" width="30" height="20"/>
+							</rectangle>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="139">
+						<jr:columnHeader style="table_CH" height="20" rowSpan="1">
+							<textField isStretchWithOverflow="true">
+								<reportElement x="0" y="0" width="139" height="20"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Notes"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="51" rowSpan="1"/>
+					</jr:column>
+				</jr:table>
+			</componentElement>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="34" splitType="Stretch">
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="17"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="14" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="14" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="17"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="17" width="200" height="17"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="17" width="82" height="17"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="34">
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="14" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="17"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="17"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="17" width="82" height="17"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="17" width="200" height="17"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="14" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<textField>
+				<reportElement key="staticText-1" x="221" y="12" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Summary"]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true">
+				<reportElement x="0" y="60" width="782" height="18"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{summaryOfCalculationMethod}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="0" y="125" width="782" height="17"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Locations found: "]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="14" y="143" width="768" height="17"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{locations}+"."]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="14" y="101" width="768" height="17"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{locationString}]]></textFieldExpression>
+			</textField>
+			<textField isStretchWithOverflow="true" pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="0" y="84" width="782" height="17"/>
+				<textElement verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Locations requested ('e.g:' is ignored, '%' is a wild card that matches zero or more characters, '_' matches any single character): "]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="782" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="14" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="782" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/stockTakeOverview.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/stockTakeOverview.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/stockTakeOverview.jrxml	(revision 753)
@@ -0,0 +1,349 @@
+<?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="reportName" language="groovy" pageWidth="595" pageHeight="842" whenNoDataType="NoDataSection" columnWidth="535" leftMargin="30" rightMargin="30" topMargin="20" bottomMargin="20" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="240"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="Crosstab Data Text" isDefault="false" hAlign="Center"/>
+	<style name="table" isDefault="false" fill="Solid" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="0.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="0.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#C7C7C7" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+		<conditionalStyle>
+			<conditionExpression><![CDATA[new Boolean($V{REPORT_COUNT}.intValue()%2==0)]]></conditionExpression>
+			<style isDefault="false" style="table_TD" backcolor="#F7F7F7"/>
+		</conditionalStyle>
+	</style>
+	<style name="table_CF" isDefault="false" mode="Opaque" backcolor="#EDEDED" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<subDataset name="dataset1">
+		<field name="store" class="java.lang.String"/>
+		<field name="location" class="java.lang.String"/>
+		<group name="group1">
+			<groupExpression><![CDATA[$F{store}]]></groupExpression>
+		</group>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="startDateString" class="java.lang.String"/>
+	<parameter name="endDateString" class="java.lang.String"/>
+	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
+		<defaultValueExpression><![CDATA["C:\\Documents and Settings\\kromhoutg\\My Documents\\reports\\"]]></defaultValueExpression>
+	</parameter>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="inventoryLocationList" class="java.util.List"/>
+	<field name="summaryOfCalculationMethod" class="java.lang.String"/>
+	<field name="inventoryLocationCount" class="java.lang.Integer"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="121" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" x="0" y="57" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="0" y="87" width="340" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Total Locations: "+$F{inventoryLocationCount}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="641" splitType="Stretch">
+			<componentElement>
+				<reportElement key="table 1" x="0" y="0" width="535" height="641"/>
+				<jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{inventoryLocationList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:column width="127">
+						<jr:groupHeader groupName="group1">
+							<jr:cell height="30" rowSpan="1">
+								<textField>
+									<reportElement x="0" y="0" width="127" height="30"/>
+									<textElement verticalAlignment="Middle">
+										<font fontName="Serif" size="12" isBold="true"/>
+									</textElement>
+									<textFieldExpression class="java.lang.String"><![CDATA[$F{store}]]></textFieldExpression>
+								</textField>
+							</jr:cell>
+						</jr:groupHeader>
+						<jr:columnHeader style="table_CH" height="30" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="127" height="30"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif" size="12" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Store: "+$F{store}]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="30" rowSpan="1"/>
+					</jr:column>
+					<jr:column width="91">
+						<jr:columnHeader style="table_CH" height="30" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="91" height="30"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif" size="12" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Location"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="30" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="91" height="30"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA[$F{location}]]></textFieldExpression>
+							</textField>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="104">
+						<jr:columnHeader style="table_CH" height="30" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="104" height="30"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="12" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Location Report Prepared"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="30" rowSpan="1">
+							<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+								<leftPen lineWidth="0.0"/>
+								<rightPen lineWidth="0.0"/>
+							</box>
+							<rectangle radius="10">
+								<reportElement x="37" y="5" width="30" height="20"/>
+							</rectangle>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="107">
+						<jr:columnHeader style="table_CH" height="30" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="107" height="30"/>
+								<textElement textAlignment="Center" verticalAlignment="Middle">
+									<font fontName="Serif" size="12" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Stock Take Complete"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="30" rowSpan="1">
+							<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+								<leftPen lineWidth="0.0"/>
+								<rightPen lineWidth="0.0"/>
+							</box>
+							<rectangle radius="10">
+								<reportElement x="38" y="5" width="30" height="20"/>
+							</rectangle>
+						</jr:detailCell>
+					</jr:column>
+					<jr:column width="107">
+						<jr:columnHeader style="table_CH" height="30" rowSpan="1">
+							<textField>
+								<reportElement x="0" y="0" width="107" height="30"/>
+								<textElement verticalAlignment="Middle">
+									<font fontName="Serif" size="12" isBold="true"/>
+								</textElement>
+								<textFieldExpression class="java.lang.String"><![CDATA["Notes"]]></textFieldExpression>
+							</textField>
+						</jr:columnHeader>
+						<jr:detailCell style="table_TD" height="30" rowSpan="1"/>
+					</jr:column>
+				</jr:table>
+			</componentElement>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="40" splitType="Stretch">
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="415" y="20" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="495" y="20" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="20" width="200" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="20" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="40">
+			<textField evaluationTime="Report">
+				<reportElement x="495" y="20" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="20" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="20" width="200" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="415" y="20" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<textField>
+				<reportElement key="staticText-1" x="97" y="12" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Summary"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="60" width="535" height="309"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{summaryOfCalculationMethod}]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="535" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="14" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="535" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/templateLandscape.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/templateLandscape.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/templateLandscape.jrxml	(revision 753)
@@ -0,0 +1,258 @@
+<?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="reportName" language="groovy" pageWidth="842" pageHeight="595" orientation="Landscape" whenNoDataType="NoDataSection" columnWidth="782" leftMargin="30" rightMargin="30" topMargin="20" bottomMargin="20" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="0"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="Crosstab Data Text" isDefault="false" hAlign="Center"/>
+	<style name="table" isDefault="false" fill="Solid" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="0.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="0.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#C7C7C7" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+		<conditionalStyle>
+			<conditionExpression><![CDATA[new Boolean($V{REPORT_COUNT}.intValue()%2==0)]]></conditionExpression>
+			<style isDefault="false" style="table_TD" backcolor="#F7F7F7"/>
+		</conditionalStyle>
+	</style>
+	<style name="table_CF" isDefault="false" mode="Opaque" backcolor="#EDEDED" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<subDataset name="dataset1">
+		<field name="description" class="java.lang.String"/>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="startDateString" class="java.lang.String"/>
+	<parameter name="endDateString" class="java.lang.String"/>
+	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
+		<defaultValueExpression><![CDATA["C:\\Documents and Settings\\kromhoutg\\My Documents\\reports\\"]]></defaultValueExpression>
+	</parameter>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="summaryOfCalculationMethod" class="java.lang.String"/>
+	<field name="dataList" class="java.util.List"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="121" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" x="0" y="57" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="0" y="87" width="340" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{startDateString}+" to "+$P{endDateString}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="268" splitType="Stretch">
+			<componentElement>
+				<reportElement x="0" y="0" width="662" height="26"/>
+				<jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" printOrder="Vertical">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:listContents height="26" width="662">
+						<textField>
+							<reportElement x="0" y="0" width="400" height="20"/>
+							<textElement>
+								<font fontName="Serif"/>
+							</textElement>
+							<textFieldExpression class="java.lang.String"><![CDATA[$F{description}]]></textFieldExpression>
+						</textField>
+					</jr:listContents>
+				</jr:list>
+			</componentElement>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="40" splitType="Stretch">
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="20" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="20" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="20" width="200" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="20" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="40">
+			<textField evaluationTime="Report">
+				<reportElement x="742" y="20" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="20" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="20" width="200" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="662" y="20" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<textField>
+				<reportElement key="staticText-1" x="221" y="12" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Summary of Calculation Method"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="50" width="782" height="311"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{summaryOfCalculationMethod}]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="782" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="14" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="782" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
Index: branches/features/taskProcedureRework/web-app/reports/templatePortrait.jrxml
===================================================================
--- branches/features/taskProcedureRework/web-app/reports/templatePortrait.jrxml	(revision 753)
+++ branches/features/taskProcedureRework/web-app/reports/templatePortrait.jrxml	(revision 753)
@@ -0,0 +1,258 @@
+<?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="reportName" language="groovy" pageWidth="595" pageHeight="842" whenNoDataType="NoDataSection" columnWidth="535" leftMargin="30" rightMargin="30" topMargin="20" bottomMargin="20" isSummaryNewPage="true" isSummaryWithPageHeaderAndFooter="true">
+	<property name="ireport.scriptlethandling" value="0"/>
+	<property name="ireport.encoding" value="UTF-8"/>
+	<property name="ireport.zoom" value="1.0"/>
+	<property name="ireport.x" value="0"/>
+	<property name="ireport.y" value="166"/>
+	<import value="net.sf.jasperreports.engine.*"/>
+	<import value="java.util.*"/>
+	<import value="net.sf.jasperreports.engine.data.*"/>
+	<style name="Crosstab Data Text" isDefault="false" hAlign="Center"/>
+	<style name="table" isDefault="false" fill="Solid" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="0.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="0.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TH" isDefault="false" mode="Opaque" backcolor="#C7C7C7" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_CH" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="0.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<style name="table_TD" isDefault="false" mode="Opaque" backcolor="#FFFFFF" fontSize="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0" lineColor="#000000"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+		<conditionalStyle>
+			<conditionExpression><![CDATA[new Boolean($V{REPORT_COUNT}.intValue()%2==0)]]></conditionExpression>
+			<style isDefault="false" style="table_TD" backcolor="#F7F7F7"/>
+		</conditionalStyle>
+	</style>
+	<style name="table_CF" isDefault="false" mode="Opaque" backcolor="#EDEDED" fontSize="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false">
+		<box topPadding="0" leftPadding="0" bottomPadding="0" rightPadding="0">
+			<pen lineWidth="1.0"/>
+			<topPen lineWidth="1.0"/>
+			<leftPen lineWidth="0.0"/>
+			<bottomPen lineWidth="1.0"/>
+			<rightPen lineWidth="0.0"/>
+		</box>
+	</style>
+	<subDataset name="dataset1">
+		<field name="description" class="java.lang.String"/>
+	</subDataset>
+	<parameter name="reportTitle" class="java.lang.String"/>
+	<parameter name="currentUser" class="java.lang.String"/>
+	<parameter name="logoUrl" class="java.lang.String"/>
+	<parameter name="startDateString" class="java.lang.String"/>
+	<parameter name="endDateString" class="java.lang.String"/>
+	<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
+		<defaultValueExpression><![CDATA["C:\\Documents and Settings\\kromhoutg\\My Documents\\reports\\"]]></defaultValueExpression>
+	</parameter>
+	<queryString language="SQL">
+		<![CDATA[]]>
+	</queryString>
+	<field name="summaryOfCalculationMethod" class="java.lang.String"/>
+	<field name="dataList" class="java.util.List"/>
+	<background>
+		<band splitType="Stretch"/>
+	</background>
+	<pageHeader>
+		<band height="121" splitType="Stretch">
+			<textField>
+				<reportElement key="staticText-1" x="0" y="57" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+			<image>
+				<reportElement x="0" y="0" width="340" height="57"/>
+				<imageExpression class="java.net.URL"><![CDATA[new URL($P{logoUrl})]]></imageExpression>
+			</image>
+			<textField pattern="dd-MMM-yyyy" isBlankWhenNull="true">
+				<reportElement x="0" y="87" width="340" height="20"/>
+				<textElement textAlignment="Center" verticalAlignment="Middle" markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{startDateString}+" to "+$P{endDateString}]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageHeader>
+	<columnHeader>
+		<band splitType="Stretch"/>
+	</columnHeader>
+	<detail>
+		<band height="268" splitType="Stretch">
+			<componentElement>
+				<reportElement x="0" y="0" width="535" height="26"/>
+				<jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" printOrder="Vertical">
+					<datasetRun subDataset="dataset1">
+						<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{dataList})]]></dataSourceExpression>
+					</datasetRun>
+					<jr:listContents height="26" width="535">
+						<textField>
+							<reportElement x="0" y="0" width="400" height="20"/>
+							<textElement>
+								<font fontName="Serif"/>
+							</textElement>
+							<textFieldExpression class="java.lang.String"><![CDATA[$F{description}]]></textFieldExpression>
+						</textField>
+					</jr:listContents>
+				</jr:list>
+			</componentElement>
+		</band>
+	</detail>
+	<columnFooter>
+		<band splitType="Stretch"/>
+	</columnFooter>
+	<pageFooter>
+		<band height="40" splitType="Stretch">
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="415" y="20" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+			<textField evaluationTime="Report">
+				<reportElement x="495" y="20" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="20" width="200" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="20" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+		</band>
+	</pageFooter>
+	<lastPageFooter>
+		<band height="40">
+			<textField evaluationTime="Report">
+				<reportElement x="495" y="20" width="40" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
+			</textField>
+			<textField pattern="dd-MMM-yyyy">
+				<reportElement x="82" y="0" width="200" height="20"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="0" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Generated: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="20" width="82" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["By: "]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="82" y="20" width="200" height="20"/>
+				<textElement markup="none">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{currentUser}]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="415" y="20" width="80" height="20"/>
+				<textElement textAlignment="Right">
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
+			</textField>
+		</band>
+	</lastPageFooter>
+	<summary>
+		<band height="369">
+			<textField>
+				<reportElement key="staticText-1" x="97" y="11" width="340" height="30"/>
+				<textElement textAlignment="Center" verticalAlignment="Top" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["Summary of Calculation Method"]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement x="0" y="50" width="535" height="311"/>
+				<textElement>
+					<font fontName="Serif"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$F{summaryOfCalculationMethod}]]></textFieldExpression>
+			</textField>
+		</band>
+	</summary>
+	<noData>
+		<band height="85" splitType="Stretch">
+			<textField>
+				<reportElement x="0" y="35" width="535" height="50"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="14" isBold="true"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA["No data to display. \n"+
+"Please run report again."]]></textFieldExpression>
+			</textField>
+			<textField>
+				<reportElement key="staticText-1" x="0" y="0" width="535" height="35"/>
+				<textElement textAlignment="Center" markup="none">
+					<font fontName="Serif" size="20"/>
+				</textElement>
+				<textFieldExpression class="java.lang.String"><![CDATA[$P{reportTitle}]]></textFieldExpression>
+			</textField>
+		</band>
+	</noData>
+</jasperReport>
