<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://rt-wiki.bestpractical.com/index.php?action=history&amp;feed=atom&amp;title=TimeWorkedReport</id>
	<title>TimeWorkedReport - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://rt-wiki.bestpractical.com/index.php?action=history&amp;feed=atom&amp;title=TimeWorkedReport"/>
	<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;action=history"/>
	<updated>2026-08-22T14:04:07Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.1</generator>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=5387&amp;oldid=prev</id>
		<title>Jbrandt at 18:56, 1 July 2016</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=5387&amp;oldid=prev"/>
		<updated>2016-07-01T18:56:05Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;amp;diff=5387&amp;amp;oldid=3881&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Jbrandt</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3881&amp;oldid=prev</id>
		<title>Admin: 9 revisions imported</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3881&amp;oldid=prev"/>
		<updated>2016-04-06T20:39:29Z</updated>

		<summary type="html">&lt;p&gt;9 revisions imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 16:39, 6 April 2016&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key bestpractical_mediawiki1459887241:diff:1.41:old-3880:rev-3881 --&gt;
&lt;/table&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3880&amp;oldid=prev</id>
		<title>41.215.133.176 at 14:02, 21 November 2013</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3880&amp;oldid=prev"/>
		<updated>2013-11-21T14:02:58Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;amp;diff=3880&amp;amp;oldid=3879&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>41.215.133.176</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3879&amp;oldid=prev</id>
		<title>208.70.247.145 at 19:11, 14 December 2012</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3879&amp;oldid=prev"/>
		<updated>2012-12-14T19:11:48Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;amp;diff=3879&amp;amp;oldid=3878&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>208.70.247.145</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3878&amp;oldid=prev</id>
		<title>77.86.29.82 at 13:57, 23 March 2012</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3878&amp;oldid=prev"/>
		<updated>2012-03-23T13:57:16Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 09:57, 23 March 2012&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l453&quot;&gt;Line 453:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 453:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** Line 47&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** Line 47&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*** currently begins with &amp;lt;code&amp;gt;&amp;amp;lt;&amp;amp;amp; /Elements/SelectMultiQueue...&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*** currently begins with &amp;lt;code&amp;gt;&amp;amp;lt;&amp;amp;amp; /Elements/SelectMultiQueue...&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*** Replace with &amp;lt;code&amp;gt;&amp;amp;lt;&amp;amp;amp; /Elements/SelectQueue, Multiple =&amp;amp;gt; 1, Name =&amp;amp;gt; &#039;queues&#039;, Default =&amp;amp;gt; ($queues) ? $queues : &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&#039;&#039; &lt;/del&gt;&amp;amp;amp;&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*** Replace with &amp;lt;code&amp;gt;&amp;amp;lt;&amp;amp;amp; /Elements/SelectQueue, Multiple =&amp;amp;gt; 1, Name =&amp;amp;gt; &#039;queues&#039;, Default =&amp;amp;gt; ($queues) ? $queues : &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&amp;amp;#39;&amp;amp;#39; &lt;/ins&gt;&amp;amp;amp;&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Restart server as instructed in step 5.  At this point, you should be able to access the report by going directly to its url ($WebBaseURL/Tools/Reports/TimeWorkedReport.html).  Next, we&amp;#039;ll add it to the Tools menu.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Restart server as instructed in step 5.  At this point, you should be able to access the report by going directly to its url ($WebBaseURL/Tools/Reports/TimeWorkedReport.html).  Next, we&amp;#039;ll add it to the Tools menu.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Create the folder $RT_HOME/local/html/Callbacks/TimeWorkedReport/Elements/Tabs&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Create the folder $RT_HOME/local/html/Callbacks/TimeWorkedReport/Elements/Tabs&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key bestpractical_mediawiki1459887241:diff:1.41:old-3877:rev-3878:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>77.86.29.82</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3877&amp;oldid=prev</id>
		<title>178.27.210.41: - optimized</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3877&amp;oldid=prev"/>
		<updated>2012-03-22T09:47:18Z</updated>

		<summary type="html">&lt;p&gt;- optimized&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;SUMMARY&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
This report allows the user to specify a datetime range and one or more queues, and displays the time worked for each ticket in the selected queue(s) which has &amp;amp;gt; 0 minutes time worked in the datetime range. It will show non-superusers their own report and superusers a report of all users.&lt;br /&gt;
&lt;br /&gt;
It also will allow superusers to organize the report by ticket, with a breakdown of the contributions to that ticket per-person, rather than the default by-person organization.&lt;br /&gt;
&lt;br /&gt;
Written by Fran Fabrizio, fabrizio -at- uab -dot- edu.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;REQUIREMENTS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
This is known to work with RT 3.8.5.  The changes needed to make it work with RT 4.0.x are outlined below.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;KNOWN BUGS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
At least two users have reported a problem with RT 3.6.x and errors related to undefined principal within the [[HasRight]] sub of [[Queue Overlay|Queue_Overlay]].pm. The RT developers changed [[HasRight]] between 3.6 and 3.8 and the code changes seem centered around undefined principals, so if anyone knows what this is and how I can code around it in a way that would work for 3.6, please contact me.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;TODO&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
This extension is still in active development. Currently, the TODO list is:&lt;br /&gt;
&lt;br /&gt;
* Figure out a better way to format this wiki page and include the code here (possible line break issues, careful when cutting and pasting)&lt;br /&gt;
* Package this as an extension with an installer&lt;br /&gt;
* Clean up the interface (align the form fields better, create a prettier report)&lt;br /&gt;
* Create a new role, something like TimeWorkedManager, rather than only showing the all-users report to SuperUsers&lt;br /&gt;
* Allow users to control extension behavior via RT&amp;#039;s Configuration area&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;FEEDBACK&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
If you have other suggestions/requests, please email me at fabrizio -at- uab -dot- edu. This is still early in development; expect rough edges.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSTALLATION&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1. Copy $RT_HOME/share/html/Tools/Reports/index.html to $RT_HOME/local/html/Tools/Reports/index.html&lt;br /&gt;
&lt;br /&gt;
Edit $RT_HOME/local/html/Tools/Reports/index.html and add the following lines to the anonymous hash pointed to by the $tabs variable (on or around line 56 of the file):&lt;br /&gt;
&lt;br /&gt;
 D =&amp;amp;gt; {&lt;br /&gt;
     title       =&amp;amp;gt; loc(&amp;#039;Time Worked Report&amp;#039;),&lt;br /&gt;
     path        =&amp;amp;gt; &amp;#039;/Tools/Reports/TimeWorkedReport.html&amp;#039;,&lt;br /&gt;
     description =&amp;amp;gt; loc(&amp;#039;A Time Worked Report&amp;#039;),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
You may need to change the &amp;quot;D&amp;quot; to the next available letter, depending on other mods that you may have made.&lt;br /&gt;
&lt;br /&gt;
2. Copy $RT_HOME/share/html/Tools/Reports/Elements/Tabs to $RT_HOME/local/html/Tools/Reports/Elements/Tabs&lt;br /&gt;
&lt;br /&gt;
Edit $RT_HOME/local/html/Tools/Reports/Elements/Tabs and add the following lines to the anonymous hash pointed to by the $tabs variable (on or around line 55 of that file):&lt;br /&gt;
&lt;br /&gt;
 d =&amp;amp;gt; {&lt;br /&gt;
     title =&amp;amp;gt; loc(&amp;#039;Time Worked Report&amp;#039;),&lt;br /&gt;
     path  =&amp;amp;gt; &amp;#039;Tools/Reports/TimeWorkedReport.html&amp;#039;,&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Again, you may need to change the &amp;quot;d&amp;quot; to the next available letter depending on other mods you may have made.&lt;br /&gt;
&lt;br /&gt;
3. Create the file $RT_HOME/local/html/Elements/SelectMultiQueue with the following content:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;%# BEGIN BPS TAGGED BLOCK {{{&lt;br /&gt;
 %#&lt;br /&gt;
 %# COPYRIGHT:&lt;br /&gt;
 %#&lt;br /&gt;
 %# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC&lt;br /&gt;
 %#                                          &amp;amp;lt;jesse@bestpractical.com&amp;amp;gt;&lt;br /&gt;
 %#&lt;br /&gt;
 %# (Except where explicitly superseded by other copyright notices)&lt;br /&gt;
 %#&lt;br /&gt;
 %#&lt;br /&gt;
 %# LICENSE:&lt;br /&gt;
 %#&lt;br /&gt;
 %# This work is made available to you under the terms of Version 2 of&lt;br /&gt;
 %# the GNU General Public License. A copy of that license should have&lt;br /&gt;
 %# been provided with this software, but in any event can be snarfed&lt;br /&gt;
 %# from www.gnu.org.&lt;br /&gt;
 %#&lt;br /&gt;
 %# This work is distributed in the hope that it will be useful, but&lt;br /&gt;
 %# WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 %# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU&lt;br /&gt;
 %# General Public License for more details.&lt;br /&gt;
 %#&lt;br /&gt;
 %# You should have received a copy of the GNU General Public License&lt;br /&gt;
 %# along with this program; if not, write to the Free Software&lt;br /&gt;
 %# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA&lt;br /&gt;
 %# 02110-1301 or visit their web page on the internet at&lt;br /&gt;
 %# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.&lt;br /&gt;
 %#&lt;br /&gt;
 %#&lt;br /&gt;
 %# CONTRIBUTION SUBMISSION POLICY:&lt;br /&gt;
 %#&lt;br /&gt;
 %# (The following paragraph is not intended to limit the rights granted&lt;br /&gt;
 %# to you to modify and distribute this software under the terms of&lt;br /&gt;
 %# the GNU General Public License and is only of importance to you if&lt;br /&gt;
 %# you choose to contribute your changes and enhancements to the&lt;br /&gt;
 %# community by submitting them to Best Practical Solutions, LLC.)&lt;br /&gt;
 %#&lt;br /&gt;
 %# By intentionally submitting any modifications, corrections or&lt;br /&gt;
 %# derivatives to this work, or any other work intended for use with&lt;br /&gt;
 %# Request Tracker, to Best Practical Solutions, LLC, you confirm that&lt;br /&gt;
 %# you are the copyright holder for those contributions and you grant&lt;br /&gt;
 %# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,&lt;br /&gt;
 %# royalty-free, perpetual, license to use, copy, create derivative&lt;br /&gt;
 %# works based on those contributions, and sublicense and distribute&lt;br /&gt;
 %# those contributions and any derivatives thereof.&lt;br /&gt;
 %#&lt;br /&gt;
 %# END BPS TAGGED BLOCK }}}&lt;br /&gt;
 % if ($Lite) {&lt;br /&gt;
 %     my $d = new RT::Queue($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
 %     $d-&amp;amp;gt;Load($Default);&lt;br /&gt;
 &amp;amp;lt;input name=&amp;quot;&amp;amp;lt;%$Name%&amp;amp;gt;&amp;quot; size=&amp;quot;25&amp;quot; value=&amp;quot;&amp;amp;lt;%$d-&amp;amp;gt;Name%&amp;amp;gt;&amp;quot; class=&amp;quot;&amp;amp;lt;%$Class%&amp;amp;gt;&amp;quot; /&amp;amp;gt;&lt;br /&gt;
 % }&lt;br /&gt;
 % else {&lt;br /&gt;
 %     # $Default will be an arrayref if multiple queues are selected, or a&lt;br /&gt;
 %     # scalar if 0-1 queues are selected.  Hence, this ugly processing logic.&lt;br /&gt;
 %     my %selected;&lt;br /&gt;
 %     if (ref $Default) {&lt;br /&gt;
 %       for (@$Default) {&lt;br /&gt;
 %         $selected{$_} = 1;&lt;br /&gt;
 %       }&lt;br /&gt;
 %     } else {&lt;br /&gt;
 %       $selected{$Default} = 1;&lt;br /&gt;
 %     }&lt;br /&gt;
 &amp;amp;lt;select name=&amp;quot;&amp;amp;lt;%$Name%&amp;amp;gt;&amp;quot; &amp;amp;lt;% ($OnChange) ? &amp;#039;onchange=&amp;quot;&amp;#039;.$OnChange.&amp;#039;&amp;quot;&amp;#039; : &amp;#039;&amp;#039; |n %&amp;amp;gt; class=&amp;quot;  &amp;amp;lt;%$Class%&amp;amp;gt;&amp;quot; MULTIPLE&amp;amp;gt;&lt;br /&gt;
 %     if ($ShowNullOption) {&lt;br /&gt;
   &amp;amp;lt;option value=&amp;quot;&amp;quot;&amp;amp;gt;-&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
 %     }&lt;br /&gt;
 %     for my $queue (@{$session{$cache_key}}) {&lt;br /&gt;
   &amp;amp;lt;option value=&amp;quot;&amp;amp;lt;% ($NamedValues ? $queue-&amp;amp;gt;{Name} : $queue-&amp;amp;gt;{Id}) %&amp;amp;gt;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 %# if ($queue-&amp;amp;gt;{Id} eq ($Default||&amp;#039;&amp;#039;) || $queue-&amp;amp;gt;{Name} eq ($Default||&amp;#039;&amp;#039;)) {&lt;br /&gt;
 % if($selected{$queue-&amp;amp;gt;{Id}}) {&lt;br /&gt;
  selected=&amp;quot;selected&amp;quot;&lt;br /&gt;
 % }&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;%$queue-&amp;amp;gt;{Name}%&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 %             if ($Verbose and $queue-&amp;amp;gt;{Description}) {&lt;br /&gt;
     (&amp;amp;lt;%$queue-&amp;amp;gt;{Description}%&amp;amp;gt;)&lt;br /&gt;
 %             }&lt;br /&gt;
   &amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
 %     }&lt;br /&gt;
 &amp;amp;lt;/select&amp;amp;gt;&lt;br /&gt;
 % }&lt;br /&gt;
 &amp;amp;lt;%args&amp;amp;gt;&lt;br /&gt;
 $CheckQueueRight =&amp;amp;gt; &amp;#039;CreateTicket&amp;#039;&lt;br /&gt;
 $ShowNullOption =&amp;amp;gt; 1&lt;br /&gt;
 $ShowAllQueues =&amp;amp;gt; 1&lt;br /&gt;
 $Name =&amp;amp;gt; undef&lt;br /&gt;
 $Verbose =&amp;amp;gt; undef&lt;br /&gt;
 $NamedValues =&amp;amp;gt; 0&lt;br /&gt;
 $Default =&amp;amp;gt; 0&lt;br /&gt;
 $Lite =&amp;amp;gt; 0&lt;br /&gt;
 $OnChange =&amp;amp;gt; undef&lt;br /&gt;
 $Class =&amp;amp;gt; &amp;#039;select-queue&amp;#039;&lt;br /&gt;
 &amp;amp;lt;/%args&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;%init&amp;amp;gt;&lt;br /&gt;
 my $cache_key = &amp;quot;SelectQueue---&amp;quot;&lt;br /&gt;
                 . $session{&amp;#039;CurrentUser&amp;#039;}-&amp;amp;gt;Id&lt;br /&gt;
                 . &amp;quot;---$CheckQueueRight---$ShowAllQueues&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 if (not defined $session{$cache_key} and not $Lite) {&lt;br /&gt;
     my $q = new RT::Queues($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
     $q-&amp;amp;gt;UnLimit;&lt;br /&gt;
 &lt;br /&gt;
     while (my $queue = $q-&amp;amp;gt;Next) {&lt;br /&gt;
         if ($ShowAllQueues || $queue-&amp;amp;gt;CurrentUserHasRight($CheckQueueRight)) {&lt;br /&gt;
             push @{$session{$cache_key}}, {&lt;br /&gt;
                 Id          =&amp;amp;gt; $queue-&amp;amp;gt;Id,&lt;br /&gt;
                 Name        =&amp;amp;gt; $queue-&amp;amp;gt;Name,&lt;br /&gt;
                 Description =&amp;amp;gt; $queue-&amp;amp;gt;Description,&lt;br /&gt;
             };&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &amp;amp;lt;/%init&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a very slightly modified form of SelectQueue which ships with RT in the same directory. You can diff the two to see what I have changed.&lt;br /&gt;
&lt;br /&gt;
4. Create the file $RT_HOME/local/html/Tools/Reports/TimeWorkedReport.html with the following content:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;amp;lt;%args&amp;amp;gt;&lt;br /&gt;
  $startdate =&amp;amp;gt; undef&lt;br /&gt;
  $enddate   =&amp;amp;gt; undef&lt;br /&gt;
  $queues    =&amp;amp;gt; undef&lt;br /&gt;
  $byticket  =&amp;amp;gt; undef&lt;br /&gt;
 &amp;amp;lt;/%args&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;&amp;amp;amp; /Elements/Header, Title =&amp;amp;gt; $title &amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;&amp;amp;amp; /Tools/Reports/Elements/Tabs, current_tab =&amp;amp;gt; &amp;#039;Tools/Reports/TimeWorkedReport.html&amp;#039;, Title  =&amp;amp;gt; $title &amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;hr&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;%init&amp;amp;gt;&lt;br /&gt;
 my ($start_date, $end_date, $effective_end_date, $title);&lt;br /&gt;
 &lt;br /&gt;
 $title = loc(&amp;#039;Time worked report&amp;#039;);&lt;br /&gt;
 &lt;br /&gt;
 $start_date = RT::Date-&amp;amp;gt;new($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
 $end_date   = RT::Date-&amp;amp;gt;new($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
 &lt;br /&gt;
 # If we have a value for start date, parse it into an RT::Date object&lt;br /&gt;
 if ($startdate) {&lt;br /&gt;
   $start_date-&amp;amp;gt;Set(Format =&amp;amp;gt; &amp;#039;unknown&amp;#039;, Value =&amp;amp;gt; $startdate);&lt;br /&gt;
   # And then get it back as an ISO string for display purposes, in the form field and&lt;br /&gt;
   # report header&lt;br /&gt;
   $startdate = $start_date-&amp;amp;gt;AsString(Format =&amp;amp;gt; &amp;#039;ISO&amp;#039;, Timezone =&amp;amp;gt; &amp;#039;server&amp;#039;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # Same treatment for end date&lt;br /&gt;
 if ($enddate) {&lt;br /&gt;
   $end_date-&amp;amp;gt;Set(Format =&amp;amp;gt; &amp;#039;unknown&amp;#039;, Value =&amp;amp;gt; $enddate);&lt;br /&gt;
   $enddate = $end_date-&amp;amp;gt;AsString(Format =&amp;amp;gt; &amp;#039;ISO&amp;#039;, Timezone =&amp;amp;gt; &amp;#039;server&amp;#039;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;/%init&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;form method=&amp;quot;post&amp;quot; action=&amp;quot;TimeWorkedReport.html&amp;quot;&amp;amp;gt;&lt;br /&gt;
  &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp;|/l&amp;amp;amp;&amp;amp;gt;Start date&amp;amp;lt;/&amp;amp;amp;&amp;amp;gt;:&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp; /Elements/SelectDate, Name =&amp;amp;gt; &amp;#039;startdate&amp;#039;, Default =&amp;amp;gt; ($startdate) ?  $start_date-&amp;amp;gt;AsString(Format =&amp;amp;gt; &amp;#039;ISO&amp;#039;, Timezone =&amp;amp;gt; &amp;#039;server&amp;#039;) : &amp;#039;&amp;#039;&amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
   (report will start from midnight on this day unless you indicate otherwise)&lt;br /&gt;
  &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp;|/l&amp;amp;amp;&amp;amp;gt;End date&amp;amp;lt;/&amp;amp;amp;&amp;amp;gt;:&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp; /Elements/SelectDate, Name =&amp;amp;gt; &amp;#039;enddate&amp;#039;, Default =&amp;amp;gt; ($enddate) ?  $end_date-&amp;amp;gt;AsString(Format =&amp;amp;gt; &amp;#039;ISO&amp;#039;, Timezone =&amp;amp;gt; &amp;#039;server&amp;#039;) : &amp;#039;&amp;#039;&amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
   (report will -not- be inclusive of this day unless you change the time from midnight)&lt;br /&gt;
  &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp;|/l&amp;amp;amp;&amp;amp;gt;Queues&amp;amp;lt;/&amp;amp;amp;&amp;amp;gt;:&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp; /Elements/SelectMultiQueue, Name =&amp;amp;gt; &amp;#039;queues&amp;#039;, Default =&amp;amp;gt; ($queues) ? $queues : &amp;#039;&amp;#039;&amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
  &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp; /Elements/Checkbox, Name =&amp;amp;gt; &amp;#039;byticket&amp;#039;, Default =&amp;amp;gt; ($byticket) ? &amp;#039;checked&amp;#039; : &amp;#039;&amp;#039;&amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
   Organize report by ticket instead of by person&lt;br /&gt;
 &amp;amp;lt;&amp;amp;amp; /Elements/Submit&amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;/form&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;%perl&amp;amp;gt;&lt;br /&gt;
 # TimeWorkedReport&lt;br /&gt;
 # Version 0.04  2009-09-28&lt;br /&gt;
 #&lt;br /&gt;
 # Fran Fabrizio, UAB CIS, fran@cis.uab.edu&lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 &lt;br /&gt;
 # if we are just getting here and the form values are empty, we are done&lt;br /&gt;
 if (!$startdate || !$enddate) {&lt;br /&gt;
   return;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # get the queue object(s)&lt;br /&gt;
 my $queuesobj = new RT::Queues($session{CurrentUser});&lt;br /&gt;
 my ($queuelist, %queuesofinterest);&lt;br /&gt;
 &lt;br /&gt;
 # The user&amp;#039;s choice of queues will come in from the web form in the $queues variable, which is&lt;br /&gt;
 # mapped to the SELECT field on the web interface for the report.  Unfortunately, if the user&lt;br /&gt;
 # chooses just one queue, $queues will have a scalar value, but if the user chooses multiple&lt;br /&gt;
 # queues, it will be an arrayref.  So we need to check for each case and process differently.&lt;br /&gt;
 #&lt;br /&gt;
 # What we want to construct is the %queuesofinterest simple lookup hash which defines a key&lt;br /&gt;
 # that is the queue ID for each queue selected, and the $queuelist string, which is just for&lt;br /&gt;
 # displaying the list of queues in the report header&lt;br /&gt;
 $queues = [ $queues ] unless ref($queues);&lt;br /&gt;
&lt;br /&gt;
 for (@$queues) {&lt;br /&gt;
   $queuesobj-&amp;gt;Limit(FIELD =&amp;gt; &amp;quot;Id&amp;quot;, OPERATOR =&amp;gt; &amp;quot;=&amp;quot;, VALUE =&amp;gt; $_, ENTRYAGGREGATOR =&amp;gt; &amp;quot;OR&amp;quot;);&lt;br /&gt;
   $queuesofinterest{$_} = 1;&lt;br /&gt;
 }&lt;br /&gt;
 $queuelist = join &amp;quot;, &amp;quot;, map {$_-&amp;gt;Name} @{$queuesobj-&amp;gt;ItemsArrayRef};&lt;br /&gt;
 &lt;br /&gt;
 # hash to hold statistics&lt;br /&gt;
 # %stats will be a multilevel hash - first level keys are the usernames, second level keys are&lt;br /&gt;
 # the ticket IDs, and for each ticket, we store an anonymous hash with keys Subject and  TimeWorked&lt;br /&gt;
 # (this implies that a single ticket can live under two+ users if they both worked the ticket)&lt;br /&gt;
 my %stats;&lt;br /&gt;
 &lt;br /&gt;
 # Get a new transactions object to hold transaction search results for this ticket&lt;br /&gt;
 my $trans = new RT::Transactions($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
 &lt;br /&gt;
 # only in the period of interest&lt;br /&gt;
 $trans-&amp;amp;gt;Limit(FIELD =&amp;amp;gt; &amp;#039;Created&amp;#039;, OPERATOR =&amp;amp;gt; &amp;#039;&amp;amp;gt;&amp;#039;, VALUE =&amp;amp;gt; $startdate);&lt;br /&gt;
 $trans-&amp;amp;gt;Limit(FIELD =&amp;amp;gt; &amp;#039;Created&amp;#039;, OPERATOR =&amp;amp;gt; &amp;#039;&amp;amp;lt;&amp;#039;, VALUE =&amp;amp;gt; $enddate, ENTRYAGGREGATOR =&amp;amp;gt;  &amp;#039;AND&amp;#039;);&lt;br /&gt;
 &lt;br /&gt;
 # now start counting all the TimeTaken by examining transactions associated with this ticket&lt;br /&gt;
 while (my $tr = $trans-&amp;amp;gt;Next) {&lt;br /&gt;
 &lt;br /&gt;
  # did this transaction take any time?  RT records this -either- in TimeTaken column or by&lt;br /&gt;
  # indicating &amp;quot;TimeWorked&amp;quot; in the Field column, depending on how the user inputted the time.&lt;br /&gt;
  if (($tr-&amp;amp;gt;TimeTaken != 0) || ($tr-&amp;amp;gt;Field &amp;amp;amp;&amp;amp;amp; $tr-&amp;amp;gt;Field eq &amp;#039;TimeWorked&amp;#039;)) {&lt;br /&gt;
    # Got a hot one - what ticket is this?&lt;br /&gt;
    my $t = new RT::Ticket($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
    $t-&amp;amp;gt;Load($tr-&amp;amp;gt;ObjectId);&lt;br /&gt;
 &lt;br /&gt;
    if (!$t) {&lt;br /&gt;
      # unable to retrieve a ticket for this transaction&lt;br /&gt;
      # hopefully we don&amp;#039;t ever reach here!&lt;br /&gt;
      next;&lt;br /&gt;
    } else {&lt;br /&gt;
      # Is a queue selected and is this ticket in a queue we care about?&lt;br /&gt;
      if ($queuelist &amp;amp;&amp;amp; !$queuesofinterest{$t-&amp;amp;gt;Queue}) {&lt;br /&gt;
        next;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    # If this is time logged by user RT_System, it&amp;#039;s the result of a ticket merge&lt;br /&gt;
    # In order to avoid double-counting minutes in --byticket mode, or the less serious&lt;br /&gt;
    # issue of displaying a report for user RT_System in normal mode, we skip this entirely&lt;br /&gt;
    if ($tr-&amp;amp;gt;CreatorObj-&amp;amp;gt;Name eq &amp;#039;RT_System&amp;#039;) {&lt;br /&gt;
      next;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    # we&amp;#039;ve got some time to account for&lt;br /&gt;
 &lt;br /&gt;
    # is this the first time this person is charging time to this ticket?&lt;br /&gt;
    # if so, add this ticket subject to the data structure&lt;br /&gt;
    if (!exists($stats{$tr-&amp;amp;gt;CreatorObj-&amp;amp;gt;Name}{$t-&amp;amp;gt;id}{Subject})) {&lt;br /&gt;
      $stats{$tr-&amp;amp;gt;CreatorObj-&amp;amp;gt;Name}{$t-&amp;amp;gt;id}{Subject} = $t-&amp;amp;gt;Subject;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    if ($tr-&amp;amp;gt;TimeTaken != 0) {&lt;br /&gt;
      # this was a comment or correspondence where the user also added some time worked&lt;br /&gt;
      # value of interest appears in Transaction&amp;#039;s TimeTaken column&lt;br /&gt;
      $stats{$tr-&amp;amp;gt;CreatorObj-&amp;amp;gt;Name}{$t-&amp;amp;gt;id}{TimeWorked} += $tr-&amp;amp;gt;TimeTaken;&lt;br /&gt;
    } else {&lt;br /&gt;
      # this was a direct update of the time worked field from the Basics or Jumbo ticket update page&lt;br /&gt;
      # values of interest appear in Transaction&amp;#039;s OldValue and NewValue columns&lt;br /&gt;
      # RT does not use the TimeTaken column in this instance.&lt;br /&gt;
      $stats{$tr-&amp;amp;gt;CreatorObj-&amp;amp;gt;Name}{$t-&amp;amp;gt;id}{TimeWorked} += $tr-&amp;amp;gt;NewValue - $tr-&amp;amp;gt;OldValue;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # report output starts here&lt;br /&gt;
 # output:&lt;br /&gt;
 #  normal user: their own time worked report, most worked ticket to least worked ticket&lt;br /&gt;
 #  superuser:   everyone&amp;#039;s time worked report, in username alpha order, then by most worked to least worked&lt;br /&gt;
 #  superuser+byticket: most worked ticket first, with everyone&amp;#039;s contribution ranked by  biggest contribution to smallest&lt;br /&gt;
 &lt;br /&gt;
 print &amp;quot;&amp;amp;lt;h2&amp;amp;gt;TIME WORKED REPORT FOR QUEUE(S) &amp;quot; . $queuelist . &amp;quot;&amp;amp;lt;/h2&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 print &amp;quot;&amp;amp;lt;h3&amp;amp;gt;Date Range: $startdate TO $enddate&amp;amp;lt;/h3&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 if ($byticket) {&lt;br /&gt;
   print &amp;quot;&amp;amp;lt;h3&amp;amp;gt;Organized by Ticket&amp;amp;lt;/h3&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 print &amp;quot;&amp;amp;lt;hr&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 # if this person is not a superuser, we should only show them the report for themselves&lt;br /&gt;
 # which means we should remove all keys from %stats except their own username&lt;br /&gt;
 if (!($session{&amp;#039;CurrentUser&amp;#039;}-&amp;amp;gt;HasRight(Right =&amp;amp;gt; &amp;#039;SuperUser&amp;#039;, Object =&amp;amp;gt; $RT::System))) {&lt;br /&gt;
   my %tempstats;&lt;br /&gt;
   $tempstats{$session{CurrentUser}-&amp;amp;gt;Name} = $stats{$session{CurrentUser}-&amp;amp;gt;Name};&lt;br /&gt;
   %stats = %tempstats;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 if ($byticket) {&lt;br /&gt;
   # if we&amp;#039;re going to organize this by ticket, we need to transform the data first&lt;br /&gt;
   # HAVE ENTRIES LIKE:  $stats{JoeUser}{12345}{TimeWorked} = 150&lt;br /&gt;
   #                     $stats{JoeUser}{12345}{Subject} = &amp;quot;Fix the Fubar Widget&amp;quot;&lt;br /&gt;
   # WANT ENTRIES LIKE:  $tstats{12345}{TotalTime} = 250&lt;br /&gt;
   #                     $tstats{12345}{Subject} = &amp;quot;Fix the Fubar Widget&amp;quot;&lt;br /&gt;
   #                     $tstats{12345}{People}{JoeUser} = 150&lt;br /&gt;
   #                     $tstats{12345}{People}{JaneDoe} = 100&lt;br /&gt;
 &lt;br /&gt;
   my %tstats;&lt;br /&gt;
   for my $person (keys %stats) {&lt;br /&gt;
     for my $tid (keys %{$stats{$person}}) {&lt;br /&gt;
       # grab the subject line if you don&amp;#039;t have it already&lt;br /&gt;
       if (!exists($tstats{$tid}{Subject})) {&lt;br /&gt;
         $tstats{$tid}{Subject} = $stats{$person}{$tid}{Subject};&lt;br /&gt;
       }&lt;br /&gt;
       # now increment total time for this ticket&lt;br /&gt;
       $tstats{$tid}{TotalTime} += $stats{$person}{$tid}{TimeWorked};&lt;br /&gt;
       # and record this user&amp;#039;s contribution to this ticket&lt;br /&gt;
       $tstats{$tid}{People}{$person} = $stats{$person}{$tid}{TimeWorked};&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   # Now emit the report&lt;br /&gt;
   for my $tid (sort {$tstats{$b}{TotalTime} &amp;amp;lt;=&amp;amp;gt; $tstats{$a}{TotalTime}} keys %tstats) {&lt;br /&gt;
     my $subject = $tstats{$tid}{Subject};&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;H3&amp;amp;gt;&amp;amp;lt;A TARGET=\&amp;quot;_TimeWorked\&amp;quot; HREF=\&amp;quot;/Ticket/Display.html?id=$tid\&amp;quot;&amp;amp;gt;$tid:  $subject&amp;amp;lt;/A&amp;amp;gt;&amp;amp;lt;/H3&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;TABLE BORDER=0 CELLSPACING=5&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     printf(&amp;quot;&amp;amp;lt;TR&amp;amp;gt;&amp;amp;lt;TH WIDTH=30&amp;amp;gt;&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;%dm&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;%.1fh&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;TOTAL TIME&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;/TR&amp;amp;gt;&amp;quot;,  $tstats{$tid}{TotalTime},($tstats{$tid}{TotalTime} / 60));&lt;br /&gt;
     for my $person (sort {$tstats{$tid}{People}{$b} &amp;amp;lt;=&amp;amp;gt; $tstats{$tid}{People}{$a}} keys %{$tstats{$tid}{People}}) {&lt;br /&gt;
       my $minutes = $tstats{$tid}{People}{$person};&lt;br /&gt;
       printf(&amp;quot;&amp;amp;lt;TR&amp;amp;gt;&amp;amp;lt;TD&amp;amp;gt;&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD&amp;amp;gt;%dm&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD&amp;amp;gt;%.1fh&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD&amp;amp;gt;%s&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;/TR&amp;amp;gt;&amp;quot;,$minutes,($minutes /60),$person);&lt;br /&gt;
     }&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;/TABLE&amp;amp;gt;&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 } else {&lt;br /&gt;
   # the existing %stats data structure is perfect for the default report, no data transform  needed&lt;br /&gt;
   for my $person (sort keys %stats) {&lt;br /&gt;
     # get the person object, so we can get the FriendlyName to use as header&lt;br /&gt;
     my $personobj = new RT::User($session{CurrentUser});&lt;br /&gt;
     $personobj-&amp;amp;gt;Load($person);&lt;br /&gt;
 &lt;br /&gt;
     print &amp;quot;&amp;amp;lt;h3&amp;amp;gt;&amp;quot; . $personobj-&amp;amp;gt;FriendlyName . &amp;quot;&amp;amp;lt;/h3&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;TABLE BORDER=0 CELLSPACING=5&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;TR&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;MINUTES&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;HOURS&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;TICKET&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;/TR&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     my $totalMinutes = 0;&lt;br /&gt;
     for my $tid (sort {$stats{$person}{$b}{TimeWorked} &amp;amp;lt;=&amp;amp;gt; $stats{$person}{$a}{TimeWorked}}  keys %{$stats{$person}}) {&lt;br /&gt;
       my $minutes = $stats{$person}{$tid}{TimeWorked};&lt;br /&gt;
       my $subject = $stats{$person}{$tid}{Subject};&lt;br /&gt;
       print &amp;quot;&amp;amp;lt;TR&amp;amp;gt;&amp;amp;lt;TD ALIGN=RIGHT&amp;amp;gt;${minutes}m&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD ALIGN=RIGHT&amp;amp;gt;&amp;quot; . sprintf(&amp;quot;%.1fh&amp;quot;,($minutes/60)) . &amp;quot;&amp;amp;lt;/TD&amp;amp;gt;&amp;quot; .&lt;br /&gt;
                 &amp;quot;&amp;amp;lt;TD&amp;amp;gt;&amp;amp;lt;A TARGET=\&amp;quot;_TimeWorked\&amp;quot; HREF=\&amp;quot;/Ticket/Display.html?id=$tid\&amp;quot;&amp;amp;gt;$tid:  $subject&amp;amp;lt;/A&amp;amp;gt;&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;/TR&amp;amp;gt;&amp;quot;;&lt;br /&gt;
       $totalMinutes += $minutes;&lt;br /&gt;
     }&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;TR&amp;amp;gt;&amp;amp;lt;TD ALIGN=RIGHT&amp;amp;gt;&amp;amp;lt;B&amp;amp;gt;${totalMinutes}m&amp;amp;lt;/B&amp;amp;gt;&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD ALIGN=RIGHT&amp;amp;gt;&amp;amp;lt;B&amp;amp;gt;&amp;quot; . sprintf(&amp;quot;%.1fh&amp;quot;,($totalMinutes/60)) . &amp;quot;&amp;amp;lt;/B&amp;amp;gt;&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD&amp;amp;gt;&amp;amp;lt;B&amp;amp;gt;TOTALS&amp;amp;lt;/B&amp;amp;gt;&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;/TR&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;/TABLE&amp;amp;gt;&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 ##### helper functions below&lt;br /&gt;
 &lt;br /&gt;
 sub form_date_string {&lt;br /&gt;
  # expects seven input params - year, month, day, hour, minute, second, offset&lt;br /&gt;
  my $year = $_[0] - 1900;&lt;br /&gt;
  my $mon = $_[1] - 1;&lt;br /&gt;
  my $day = $_[2];&lt;br /&gt;
  my $hour = $_[3] ? $_[3] : 0;&lt;br /&gt;
  my $min = $_[4] ? $_[4] : 0;&lt;br /&gt;
  my $sec = $_[5] ? $_[5] : 0;&lt;br /&gt;
  my $offset = $_[6] ? $_[6] : 0;&lt;br /&gt;
 &lt;br /&gt;
  # convert to seconds since epoch, then adjust for the $offset, which is also in seconds&lt;br /&gt;
  # we do this so we don&amp;#039;t have to do fancy date arithmetic - we can just subtract one seconds&lt;br /&gt;
  # value from the other seconds value&lt;br /&gt;
  my $starttime = timelocal($sec,$min,$hour,$day,$mon,$year) - $offset;&lt;br /&gt;
 &lt;br /&gt;
  # convert back to component parts now that we&amp;#039;ve adjusted for offset&lt;br /&gt;
  # this gives us the components which represent the GMT time for the local time that was entered&lt;br /&gt;
  # on the command line&lt;br /&gt;
  ($sec,$min,$hour,$day,$mon,$year) = localtime($starttime);&lt;br /&gt;
 &lt;br /&gt;
  # format the date string, padding with zeros if needed&lt;br /&gt;
  return sprintf(&amp;quot;%04d-%02d-%02d %02d:%02d:%02d&amp;quot;, ($year+1900), ($mon+1), $day, $hour, $min, $sec);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;/%perl&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. Restart your server (unless you are using SetDevelMode, in which case restart is unnecessary).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;TWEAKS FOR RT4 COMPATIBILITY&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* Skip installation steps 1 and 2 above.  (RT4 uses a different mechanism for building menus and navigation.  More on that later.)&lt;br /&gt;
* Skip installation step 3.  (This functionality is now built into the SelectQueue element included in RT4, so a separate element is no longer needed.)&lt;br /&gt;
* Install the TimeWorkedReport.html as instructed in step 4, making the following modifications:&lt;br /&gt;
** Line 9 &lt;br /&gt;
*** currently begins with &amp;lt;code&amp;gt;&amp;amp;lt;&amp;amp;amp; /Tools/Reports/Elements/Tabs...&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Replace with &amp;lt;code&amp;gt;&amp;amp;lt;&amp;amp;amp; /Elements/Tabs &amp;amp;amp;&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
** Line 47&lt;br /&gt;
*** currently begins with &amp;lt;code&amp;gt;&amp;amp;lt;&amp;amp;amp; /Elements/SelectMultiQueue...&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Replace with &amp;lt;code&amp;gt;&amp;amp;lt;&amp;amp;amp; /Elements/SelectQueue, Multiple =&amp;amp;gt; 1, Name =&amp;amp;gt; &amp;#039;queues&amp;#039;, Default =&amp;amp;gt; ($queues) ? $queues : &amp;#039;&amp;#039; &amp;amp;amp;&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Restart server as instructed in step 5.  At this point, you should be able to access the report by going directly to its url ($WebBaseURL/Tools/Reports/TimeWorkedReport.html).  Next, we&amp;#039;ll add it to the Tools menu.&lt;br /&gt;
* Create the folder $RT_HOME/local/html/Callbacks/TimeWorkedReport/Elements/Tabs&lt;br /&gt;
* In that folder, create a file called Privileged with the following contents:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;amp;lt;%init&amp;amp;gt;&lt;br /&gt;
 my $tools = Menu()-&amp;amp;gt;child(&amp;#039;tools&amp;#039;);&lt;br /&gt;
 $tools-&amp;amp;gt;child( timeworked =&amp;amp;gt; title =&amp;amp;gt; &amp;#039;Time Worked Report&amp;#039;, path =&amp;amp;gt; &amp;#039;/Tools/Reports/TimeWorkedReport.html&amp;#039;, description =&amp;amp;gt; &amp;#039;Time Worked Report&amp;#039; );&lt;br /&gt;
 &amp;amp;lt;/%init&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;%args&amp;amp;gt;&lt;br /&gt;
 $Actions =&amp;amp;gt; undef&lt;br /&gt;
 &amp;amp;lt;/%args&amp;amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
* Restart the server again as instructed in step 5.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Much below this line needs cleanup and dates to when this was a standalone CLI script&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;GENERAL IMPLEMENTATION STRATEGY&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
I took a transaction-based approach. I use a SearchBuilder to grab all of the transactions that took place in the time period of interest (see TIME VALUES IN RT / HOW TO SPECIFY DATE RANGES below for time zone issue discussion). I then look at each one and go through the following workflow:&lt;br /&gt;
&lt;br /&gt;
 1. Does this transaction represent a time worked modification?&lt;br /&gt;
    (see INCONSISTENT RECORDING OF TIME WORKED below for issues here)  If no,&lt;br /&gt;
    skip to next transaction.&lt;br /&gt;
 2. Use this transaction&amp;#039;s object ID to retrieve the associated ticket object.&lt;br /&gt;
    If this fails, report the error and skip to next transaction.&lt;br /&gt;
 3. Is this ticket in a queue of interest? If no, skip to next transaction.&lt;br /&gt;
 4. Was this transaction entered by the user RT_System?  If so, it is the result&lt;br /&gt;
    of a merge operation.  Don&amp;#039;t count this time and skip to the next transaction.&lt;br /&gt;
    (The time will be captured elsewhere, under the original user that entered it,&lt;br /&gt;
    if it originally occurred in this time period of interest).&lt;br /&gt;
 &lt;br /&gt;
 Ok, if we got this far, we have real time to account for.&lt;br /&gt;
 &lt;br /&gt;
 5. If this is the first time we are seeing this person for this ticket, create the&lt;br /&gt;
    multilevel data structure to store ticket and time worked info.&lt;br /&gt;
 6. Increment the time worked value (see INCONSISTENT RECORDING OF TIME WORKED below&lt;br /&gt;
    for issues here).&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;TIME VALUES IN RT / HOW TO SPECIFY DATE RANGES&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Internally in the database, RT stores time values as gmtime. This has implications for this script, which are best illustrated by an example.&lt;br /&gt;
&lt;br /&gt;
I live in the US/Central time zone which is -18000 seconds, or -5 hours, off from GM time. I also like to work late at night. If I enter some time worked onto a ticket at 11pm on August 12th, or more formally, at &amp;quot;2009-08-12 23:00:00&amp;quot; in US Central time, that will be entered in the transaction table with a timestamp of &amp;quot;2009-08-13 04:00:00&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Now if I run this script with a startdate of &amp;quot;2009-08-12 00:00:00&amp;quot; and an enddate of &amp;quot;2009-08-12 23:59:59&amp;quot;, I would reasonably expect to get all of the time I worked on August 12th, 2009. However, I would miss the last 5 hours in the day worth of transactions, because RT would have internally shifted the stored timestamp to a time in August 13th (which it already was, over in London!)&lt;br /&gt;
&lt;br /&gt;
So, I assume that users of this script will be entering their time in their local location, and automatically adjust for this. In my case, this means when I enter a start or end date like &amp;quot;2009-08-12 00:00:00&amp;quot;, this script will convert that to &amp;quot;2009-08-12 05:00:00&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Unrelated to this issue but also relevant to the area of time values, MySQL will treat the absence of the HH:MM:SS as 00:00:00.&lt;br /&gt;
&lt;br /&gt;
In sum, if you want all the time worked for a week, let&amp;#039;s say, from Sunday, August 9th through Saturday, August 15th (inclusive), if you use the start and end values &amp;quot;2009-08-09&amp;quot; and &amp;quot;2009-08-16&amp;quot; (Note: 16 not 15!) this script will do the right thing. To be more clear, you might use &amp;quot;2009-08-09&amp;quot; and &amp;quot;2009-08-15 23:59:59&amp;quot;, but I am lazy and don&amp;#039;t mind counting the first second of the 16th as part of the 15th. :-)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INCONSISTENT RECORDING OF TIME WORKED&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Time can be entered on tickets in two main ways.&lt;br /&gt;
&lt;br /&gt;
 1. Putting a value in the Time Worked field as part of a Comment or Correspondence transaction.&lt;br /&gt;
 2. Directly editing the Time Worked field as part of a Basic or Jumbo ticket update.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Unfortunately, the way that the time gets recorded is different for each scenario.&lt;br /&gt;
&lt;br /&gt;
For scenario 1, in the transaction table the transaction will store the new time worked in the TimeTaken field as minutes.&lt;br /&gt;
&lt;br /&gt;
For scenario 2, in the transaction table the transaction will use the OldValue and NewValue fields to store the old and new values.&lt;br /&gt;
&lt;br /&gt;
So, the script needs to check for both cases, and in scenario 2, has to do a little math to figure out how much time was added.&lt;/div&gt;</summary>
		<author><name>178.27.210.41</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3875&amp;oldid=prev</id>
		<title>91.196.240.148 at 10:04, 28 March 2011</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3875&amp;oldid=prev"/>
		<updated>2011-03-28T10:04:07Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 06:04, 28 March 2011&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l32&quot;&gt;Line 32:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 32:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;1. Copy $RT_HOME/share/html/Tools/Reports/index.html to $RT_HOME/local/html/Tools/Reports/index.html&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;1. Copy $RT_HOME/share/html/Tools/Reports/index.html to $RT_HOME/local/html/Tools/Reports/index.html&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Edit $RT_HOME/local/html/Tools/Reports/index.html and add the following lines to the anonymous hash pointed to by the $tabs variable (on or around line 56 of the file):&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Edit $RT_HOME/local/html/Tools/Reports/index.html and add the following lines to the anonymous hash pointed to by the $tabs variable (on or around line 56 of the file):&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l44&quot;&gt;Line 44:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 45:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;2. Copy $RT_HOME/share/html/Tools/Reports/Elements/Tabs to $RT_HOME/local/html/Tools/Reports/Elements/Tabs&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;2. Copy $RT_HOME/share/html/Tools/Reports/Elements/Tabs to $RT_HOME/local/html/Tools/Reports/Elements/Tabs&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Edit $RT_HOME/local/html/Tools/Reports/Elements/Tabs and add the following lines to the anonymous hash pointed to by the $tabs variable (on or around line 55 of that file):&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Edit $RT_HOME/local/html/Tools/Reports/Elements/Tabs and add the following lines to the anonymous hash pointed to by the $tabs variable (on or around line 55 of that file):&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key bestpractical_mediawiki1459887241:diff:1.41:old-3874:rev-3875:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>91.196.240.148</name></author>
	</entry>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3874&amp;oldid=prev</id>
		<title>91.196.240.148: Changed to using local</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TimeWorkedReport&amp;diff=3874&amp;oldid=prev"/>
		<updated>2011-03-28T10:03:32Z</updated>

		<summary type="html">&lt;p&gt;Changed to using local&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;SUMMARY&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
This report allows the user to specify a datetime range and one or more queues, and displays the time worked for each ticket in the selected queue(s) which has &amp;amp;gt; 0 minutes time worked in the datetime range. It will show non-superusers their own report and superusers a report of all users.&lt;br /&gt;
&lt;br /&gt;
It also will allow superusers to organize the report by ticket, with a breakdown of the contributions to that ticket per-person, rather than the default by-person organization.&lt;br /&gt;
&lt;br /&gt;
Written by Fran Fabrizio, fabrizio -at- uab -dot- edu.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;REQUIREMENTS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
This is known to work with RT 3.8.5.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;KNOWN BUGS&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
At least two users have reported a problem with RT 3.6.x and errors related to undefined principal within the [[HasRight]] sub of [[Queue Overlay|Queue_Overlay]].pm. The RT developers changed [[HasRight]] between 3.6 and 3.8 and the code changes seem centered around undefined principals, so if anyone knows what this is and how I can code around it in a way that would work for 3.6, please contact me.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;TODO&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
This extension is still in active development. Currently, the TODO list is:&lt;br /&gt;
&lt;br /&gt;
* Figure out a better way to format this wiki page and include the code here (possible line break issues, careful when cutting and pasting)&lt;br /&gt;
* Package this as an extension with an installer&lt;br /&gt;
* Clean up the interface (align the form fields better, create a prettier report)&lt;br /&gt;
* Create a new role, something like TimeWorkedManager, rather than only showing the all-users report to SuperUsers&lt;br /&gt;
* Allow users to control extension behavior via RT&amp;#039;s Configuration area&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;FEEDBACK&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
If you have other suggestions/requests, please email me at fabrizio -at- uab -dot- edu. This is still early in development; expect rough edges.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INSTALLATION&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
1. Copy $RT_HOME/share/html/Tools/Reports/index.html to $RT_HOME/local/html/Tools/Reports/index.html&lt;br /&gt;
Edit $RT_HOME/local/html/Tools/Reports/index.html and add the following lines to the anonymous hash pointed to by the $tabs variable (on or around line 56 of the file):&lt;br /&gt;
&lt;br /&gt;
 D =&amp;amp;gt; {&lt;br /&gt;
     title       =&amp;amp;gt; loc(&amp;#039;Time Worked Report&amp;#039;),&lt;br /&gt;
     path        =&amp;amp;gt; &amp;#039;/Tools/Reports/TimeWorkedReport.html&amp;#039;,&lt;br /&gt;
     description =&amp;amp;gt; loc(&amp;#039;A Time Worked Report&amp;#039;),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
You may need to change the &amp;quot;D&amp;quot; to the next available letter, depending on other mods that you may have made.&lt;br /&gt;
&lt;br /&gt;
2. Copy $RT_HOME/share/html/Tools/Reports/Elements/Tabs to $RT_HOME/local/html/Tools/Reports/Elements/Tabs&lt;br /&gt;
Edit $RT_HOME/local/html/Tools/Reports/Elements/Tabs and add the following lines to the anonymous hash pointed to by the $tabs variable (on or around line 55 of that file):&lt;br /&gt;
&lt;br /&gt;
 d =&amp;amp;gt; {&lt;br /&gt;
     title =&amp;amp;gt; loc(&amp;#039;Time Worked Report&amp;#039;),&lt;br /&gt;
     path  =&amp;amp;gt; &amp;#039;Tools/Reports/TimeWorkedReport.html&amp;#039;,&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Again, you may need to change the &amp;quot;d&amp;quot; to the next available letter depending on other mods you may have made.&lt;br /&gt;
&lt;br /&gt;
3. Create the file $RT_HOME/local/html/Elements/SelectMultiQueue with the following content:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;%# BEGIN BPS TAGGED BLOCK {{{&lt;br /&gt;
 %#&lt;br /&gt;
 %# COPYRIGHT:&lt;br /&gt;
 %#&lt;br /&gt;
 %# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC&lt;br /&gt;
 %#                                          &amp;amp;lt;jesse@bestpractical.com&amp;amp;gt;&lt;br /&gt;
 %#&lt;br /&gt;
 %# (Except where explicitly superseded by other copyright notices)&lt;br /&gt;
 %#&lt;br /&gt;
 %#&lt;br /&gt;
 %# LICENSE:&lt;br /&gt;
 %#&lt;br /&gt;
 %# This work is made available to you under the terms of Version 2 of&lt;br /&gt;
 %# the GNU General Public License. A copy of that license should have&lt;br /&gt;
 %# been provided with this software, but in any event can be snarfed&lt;br /&gt;
 %# from www.gnu.org.&lt;br /&gt;
 %#&lt;br /&gt;
 %# This work is distributed in the hope that it will be useful, but&lt;br /&gt;
 %# WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
 %# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU&lt;br /&gt;
 %# General Public License for more details.&lt;br /&gt;
 %#&lt;br /&gt;
 %# You should have received a copy of the GNU General Public License&lt;br /&gt;
 %# along with this program; if not, write to the Free Software&lt;br /&gt;
 %# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA&lt;br /&gt;
 %# 02110-1301 or visit their web page on the internet at&lt;br /&gt;
 %# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.&lt;br /&gt;
 %#&lt;br /&gt;
 %#&lt;br /&gt;
 %# CONTRIBUTION SUBMISSION POLICY:&lt;br /&gt;
 %#&lt;br /&gt;
 %# (The following paragraph is not intended to limit the rights granted&lt;br /&gt;
 %# to you to modify and distribute this software under the terms of&lt;br /&gt;
 %# the GNU General Public License and is only of importance to you if&lt;br /&gt;
 %# you choose to contribute your changes and enhancements to the&lt;br /&gt;
 %# community by submitting them to Best Practical Solutions, LLC.)&lt;br /&gt;
 %#&lt;br /&gt;
 %# By intentionally submitting any modifications, corrections or&lt;br /&gt;
 %# derivatives to this work, or any other work intended for use with&lt;br /&gt;
 %# Request Tracker, to Best Practical Solutions, LLC, you confirm that&lt;br /&gt;
 %# you are the copyright holder for those contributions and you grant&lt;br /&gt;
 %# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,&lt;br /&gt;
 %# royalty-free, perpetual, license to use, copy, create derivative&lt;br /&gt;
 %# works based on those contributions, and sublicense and distribute&lt;br /&gt;
 %# those contributions and any derivatives thereof.&lt;br /&gt;
 %#&lt;br /&gt;
 %# END BPS TAGGED BLOCK }}}&lt;br /&gt;
 % if ($Lite) {&lt;br /&gt;
 %     my $d = new RT::Queue($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
 %     $d-&amp;amp;gt;Load($Default);&lt;br /&gt;
 &amp;amp;lt;input name=&amp;quot;&amp;amp;lt;%$Name%&amp;amp;gt;&amp;quot; size=&amp;quot;25&amp;quot; value=&amp;quot;&amp;amp;lt;%$d-&amp;amp;gt;Name%&amp;amp;gt;&amp;quot; class=&amp;quot;&amp;amp;lt;%$Class%&amp;amp;gt;&amp;quot; /&amp;amp;gt;&lt;br /&gt;
 % }&lt;br /&gt;
 % else {&lt;br /&gt;
 %     # $Default will be an arrayref if multiple queues are selected, or a&lt;br /&gt;
 %     # scalar if 0-1 queues are selected.  Hence, this ugly processing logic.&lt;br /&gt;
 %     my %selected;&lt;br /&gt;
 %     if (ref $Default) {&lt;br /&gt;
 %       for (@$Default) {&lt;br /&gt;
 %         $selected{$_} = 1;&lt;br /&gt;
 %       }&lt;br /&gt;
 %     } else {&lt;br /&gt;
 %       $selected{$Default} = 1;&lt;br /&gt;
 %     }&lt;br /&gt;
 &amp;amp;lt;select name=&amp;quot;&amp;amp;lt;%$Name%&amp;amp;gt;&amp;quot; &amp;amp;lt;% ($OnChange) ? &amp;#039;onchange=&amp;quot;&amp;#039;.$OnChange.&amp;#039;&amp;quot;&amp;#039; : &amp;#039;&amp;#039; |n %&amp;amp;gt; class=&amp;quot;  &amp;amp;lt;%$Class%&amp;amp;gt;&amp;quot; MULTIPLE&amp;amp;gt;&lt;br /&gt;
 %     if ($ShowNullOption) {&lt;br /&gt;
   &amp;amp;lt;option value=&amp;quot;&amp;quot;&amp;amp;gt;-&amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
 %     }&lt;br /&gt;
 %     for my $queue (@{$session{$cache_key}}) {&lt;br /&gt;
   &amp;amp;lt;option value=&amp;quot;&amp;amp;lt;% ($NamedValues ? $queue-&amp;amp;gt;{Name} : $queue-&amp;amp;gt;{Id}) %&amp;amp;gt;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 %# if ($queue-&amp;amp;gt;{Id} eq ($Default||&amp;#039;&amp;#039;) || $queue-&amp;amp;gt;{Name} eq ($Default||&amp;#039;&amp;#039;)) {&lt;br /&gt;
 % if($selected{$queue-&amp;amp;gt;{Id}}) {&lt;br /&gt;
  selected=&amp;quot;selected&amp;quot;&lt;br /&gt;
 % }&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;gt;&lt;br /&gt;
     &amp;amp;lt;%$queue-&amp;amp;gt;{Name}%&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 %             if ($Verbose and $queue-&amp;amp;gt;{Description}) {&lt;br /&gt;
     (&amp;amp;lt;%$queue-&amp;amp;gt;{Description}%&amp;amp;gt;)&lt;br /&gt;
 %             }&lt;br /&gt;
   &amp;amp;lt;/option&amp;amp;gt;&lt;br /&gt;
 %     }&lt;br /&gt;
 &amp;amp;lt;/select&amp;amp;gt;&lt;br /&gt;
 % }&lt;br /&gt;
 &amp;amp;lt;%args&amp;amp;gt;&lt;br /&gt;
 $CheckQueueRight =&amp;amp;gt; &amp;#039;CreateTicket&amp;#039;&lt;br /&gt;
 $ShowNullOption =&amp;amp;gt; 1&lt;br /&gt;
 $ShowAllQueues =&amp;amp;gt; 1&lt;br /&gt;
 $Name =&amp;amp;gt; undef&lt;br /&gt;
 $Verbose =&amp;amp;gt; undef&lt;br /&gt;
 $NamedValues =&amp;amp;gt; 0&lt;br /&gt;
 $Default =&amp;amp;gt; 0&lt;br /&gt;
 $Lite =&amp;amp;gt; 0&lt;br /&gt;
 $OnChange =&amp;amp;gt; undef&lt;br /&gt;
 $Class =&amp;amp;gt; &amp;#039;select-queue&amp;#039;&lt;br /&gt;
 &amp;amp;lt;/%args&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;%init&amp;amp;gt;&lt;br /&gt;
 my $cache_key = &amp;quot;SelectQueue---&amp;quot;&lt;br /&gt;
                 . $session{&amp;#039;CurrentUser&amp;#039;}-&amp;amp;gt;Id&lt;br /&gt;
                 . &amp;quot;---$CheckQueueRight---$ShowAllQueues&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 if (not defined $session{$cache_key} and not $Lite) {&lt;br /&gt;
     my $q = new RT::Queues($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
     $q-&amp;amp;gt;UnLimit;&lt;br /&gt;
 &lt;br /&gt;
     while (my $queue = $q-&amp;amp;gt;Next) {&lt;br /&gt;
         if ($ShowAllQueues || $queue-&amp;amp;gt;CurrentUserHasRight($CheckQueueRight)) {&lt;br /&gt;
             push @{$session{$cache_key}}, {&lt;br /&gt;
                 Id          =&amp;amp;gt; $queue-&amp;amp;gt;Id,&lt;br /&gt;
                 Name        =&amp;amp;gt; $queue-&amp;amp;gt;Name,&lt;br /&gt;
                 Description =&amp;amp;gt; $queue-&amp;amp;gt;Description,&lt;br /&gt;
             };&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &amp;amp;lt;/%init&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a very slightly modified form of SelectQueue which ships with RT in the same directory. You can diff the two to see what I have changed.&lt;br /&gt;
&lt;br /&gt;
4. Create the file $RT_HOME/local/html/Tools/Reports/TimeWorkedReport.html with the following content:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;amp;lt;%args&amp;amp;gt;&lt;br /&gt;
  $startdate =&amp;amp;gt; undef&lt;br /&gt;
  $enddate   =&amp;amp;gt; undef&lt;br /&gt;
  $queues    =&amp;amp;gt; undef&lt;br /&gt;
  $byticket  =&amp;amp;gt; undef&lt;br /&gt;
 &amp;amp;lt;/%args&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;&amp;amp;amp; /Elements/Header, Title =&amp;amp;gt; $title &amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;&amp;amp;amp; /Tools/Reports/Elements/Tabs, current_tab =&amp;amp;gt; &amp;#039;Tools/Reports/TimeWorkedReport.html&amp;#039;, Title  =&amp;amp;gt; $title &amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
 &amp;amp;lt;hr&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;%init&amp;amp;gt;&lt;br /&gt;
 my ($start_date, $end_date, $effective_end_date, $title);&lt;br /&gt;
 &lt;br /&gt;
 $title = loc(&amp;#039;Time worked report&amp;#039;);&lt;br /&gt;
 &lt;br /&gt;
 $start_date = RT::Date-&amp;amp;gt;new($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
 $end_date   = RT::Date-&amp;amp;gt;new($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
 &lt;br /&gt;
 # If we have a value for start date, parse it into an RT::Date object&lt;br /&gt;
 if ($startdate) {&lt;br /&gt;
   $start_date-&amp;amp;gt;Set(Format =&amp;amp;gt; &amp;#039;unknown&amp;#039;, Value =&amp;amp;gt; $startdate);&lt;br /&gt;
   # And then get it back as an ISO string for display purposes, in the form field and&lt;br /&gt;
   # report header&lt;br /&gt;
   $startdate = $start_date-&amp;amp;gt;AsString(Format =&amp;amp;gt; &amp;#039;ISO&amp;#039;, Timezone =&amp;amp;gt; &amp;#039;server&amp;#039;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # Same treatment for end date&lt;br /&gt;
 if ($enddate) {&lt;br /&gt;
   $end_date-&amp;amp;gt;Set(Format =&amp;amp;gt; &amp;#039;unknown&amp;#039;, Value =&amp;amp;gt; $enddate);&lt;br /&gt;
   $enddate = $end_date-&amp;amp;gt;AsString(Format =&amp;amp;gt; &amp;#039;ISO&amp;#039;, Timezone =&amp;amp;gt; &amp;#039;server&amp;#039;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;/%init&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;form method=&amp;quot;post&amp;quot; action=&amp;quot;TimeWorkedReport.html&amp;quot;&amp;amp;gt;&lt;br /&gt;
  &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp;|/l&amp;amp;amp;&amp;amp;gt;Start date&amp;amp;lt;/&amp;amp;amp;&amp;amp;gt;:&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp; /Elements/SelectDate, Name =&amp;amp;gt; &amp;#039;startdate&amp;#039;, Default =&amp;amp;gt; ($startdate) ?  $start_date-&amp;amp;gt;AsString(Format =&amp;amp;gt; &amp;#039;ISO&amp;#039;, Timezone =&amp;amp;gt; &amp;#039;server&amp;#039;) : &amp;#039;&amp;#039;&amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
   (report will start from midnight on this day unless you indicate otherwise)&lt;br /&gt;
  &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp;|/l&amp;amp;amp;&amp;amp;gt;End date&amp;amp;lt;/&amp;amp;amp;&amp;amp;gt;:&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp; /Elements/SelectDate, Name =&amp;amp;gt; &amp;#039;enddate&amp;#039;, Default =&amp;amp;gt; ($enddate) ?  $end_date-&amp;amp;gt;AsString(Format =&amp;amp;gt; &amp;#039;ISO&amp;#039;, Timezone =&amp;amp;gt; &amp;#039;server&amp;#039;) : &amp;#039;&amp;#039;&amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
   (report will -not- be inclusive of this day unless you change the time from midnight)&lt;br /&gt;
  &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp;|/l&amp;amp;amp;&amp;amp;gt;Queues&amp;amp;lt;/&amp;amp;amp;&amp;amp;gt;:&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp; /Elements/SelectMultiQueue, Name =&amp;amp;gt; &amp;#039;queues&amp;#039;, Default =&amp;amp;gt; ($queues) ? $queues : &amp;#039;&amp;#039;&amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
  &amp;amp;lt;br /&amp;amp;gt;&lt;br /&gt;
   &amp;amp;lt;&amp;amp;amp; /Elements/Checkbox, Name =&amp;amp;gt; &amp;#039;byticket&amp;#039;, Default =&amp;amp;gt; ($byticket) ? &amp;#039;checked&amp;#039; : &amp;#039;&amp;#039;&amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
   Organize report by ticket instead of by person&lt;br /&gt;
 &amp;amp;lt;&amp;amp;amp; /Elements/Submit&amp;amp;amp;&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;/form&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;%perl&amp;amp;gt;&lt;br /&gt;
 # TimeWorkedReport&lt;br /&gt;
 # Version 0.04  2009-09-28&lt;br /&gt;
 #&lt;br /&gt;
 # Fran Fabrizio, UAB CIS, fran@cis.uab.edu&lt;br /&gt;
 &lt;br /&gt;
 use strict;&lt;br /&gt;
 &lt;br /&gt;
 # if we are just getting here and the form values are empty, we are done&lt;br /&gt;
 if (!$startdate || !$enddate) {&lt;br /&gt;
   return;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # get the queue object(s)&lt;br /&gt;
 my $queuesobj = new RT::Queues($session{CurrentUser});&lt;br /&gt;
 my ($queuelist, %queuesofinterest);&lt;br /&gt;
 &lt;br /&gt;
 # The user&amp;#039;s choice of queues will come in from the web form in the $queues variable, which is&lt;br /&gt;
 # mapped to the SELECT field on the web interface for the report.  Unfortunately, if the user&lt;br /&gt;
 # chooses just one queue, $queues will have a scalar value, but if the user chooses multiple&lt;br /&gt;
 # queues, it will be an arrayref.  So we need to check for each case and process differently.&lt;br /&gt;
 #&lt;br /&gt;
 # What we want to construct is the %queuesofinterest simple lookup hash which defines a key&lt;br /&gt;
 # that is the queue ID for each queue selected, and the $queuelist string, which is just for&lt;br /&gt;
 # displaying the list of queues in the report header&lt;br /&gt;
 if (ref $queues) {&lt;br /&gt;
   # multiple queues selected&lt;br /&gt;
   for (@$queues) {&lt;br /&gt;
     $queuesobj-&amp;amp;gt;Limit(FIELD =&amp;amp;gt; &amp;quot;Id&amp;quot;, OPERATOR =&amp;amp;gt; &amp;quot;=&amp;quot;, VALUE =&amp;amp;gt; $_, ENTRYAGGREGATOR =&amp;amp;gt; &amp;quot;OR&amp;quot;);&lt;br /&gt;
     $queuesofinterest{$_} = 1;&lt;br /&gt;
   }&lt;br /&gt;
   $queuelist = join &amp;quot;, &amp;quot;, map {$_-&amp;amp;gt;Name} @{$queuesobj-&amp;amp;gt;ItemsArrayRef};&lt;br /&gt;
 } else {&lt;br /&gt;
   my $queue = new RT::Queue;&lt;br /&gt;
   $queue-&amp;amp;gt;Load(Id =&amp;amp;gt; $queues);&lt;br /&gt;
   $queuesofinterest{$queues} = 1;&lt;br /&gt;
   $queuelist = $queue-&amp;amp;gt;Name;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # hash to hold statistics&lt;br /&gt;
 # %stats will be a multilevel hash - first level keys are the usernames, second level keys are&lt;br /&gt;
 # the ticket IDs, and for each ticket, we store an anonymous hash with keys Subject and  TimeWorked&lt;br /&gt;
 # (this implies that a single ticket can live under two+ users if they both worked the ticket)&lt;br /&gt;
 my %stats;&lt;br /&gt;
 &lt;br /&gt;
 # Get a new transactions object to hold transaction search results for this ticket&lt;br /&gt;
 my $trans = new RT::Transactions($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
 &lt;br /&gt;
 # only in the period of interest&lt;br /&gt;
 $trans-&amp;amp;gt;Limit(FIELD =&amp;amp;gt; &amp;#039;Created&amp;#039;, OPERATOR =&amp;amp;gt; &amp;#039;&amp;amp;gt;&amp;#039;, VALUE =&amp;amp;gt; $startdate);&lt;br /&gt;
 $trans-&amp;amp;gt;Limit(FIELD =&amp;amp;gt; &amp;#039;Created&amp;#039;, OPERATOR =&amp;amp;gt; &amp;#039;&amp;amp;lt;&amp;#039;, VALUE =&amp;amp;gt; $enddate, ENTRYAGGREGATOR =&amp;amp;gt;  &amp;#039;AND&amp;#039;);&lt;br /&gt;
 &lt;br /&gt;
 # now start counting all the TimeTaken by examining transactions associated with this ticket&lt;br /&gt;
 while (my $tr = $trans-&amp;amp;gt;Next) {&lt;br /&gt;
 &lt;br /&gt;
  # did this transaction take any time?  RT records this -either- in TimeTaken column or by&lt;br /&gt;
  # indicating &amp;quot;TimeWorked&amp;quot; in the Field column, depending on how the user inputted the time.&lt;br /&gt;
  if (($tr-&amp;amp;gt;TimeTaken != 0) || ($tr-&amp;amp;gt;Field &amp;amp;amp;&amp;amp;amp; $tr-&amp;amp;gt;Field eq &amp;#039;TimeWorked&amp;#039;)) {&lt;br /&gt;
    # Got a hot one - what ticket is this?&lt;br /&gt;
    my $t = new RT::Ticket($session{&amp;#039;CurrentUser&amp;#039;});&lt;br /&gt;
    $t-&amp;amp;gt;Load($tr-&amp;amp;gt;ObjectId);&lt;br /&gt;
 &lt;br /&gt;
    if (!$t) {&lt;br /&gt;
      # unable to retrieve a ticket for this transaction&lt;br /&gt;
      # hopefully we don&amp;#039;t ever reach here!&lt;br /&gt;
      next;&lt;br /&gt;
    } else {&lt;br /&gt;
      # Is this ticket in a queue we care about?&lt;br /&gt;
      if (!$queuesofinterest{$t-&amp;amp;gt;Queue}) {&lt;br /&gt;
        next;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    # If this is time logged by user RT_System, it&amp;#039;s the result of a ticket merge&lt;br /&gt;
    # In order to avoid double-counting minutes in --byticket mode, or the less serious&lt;br /&gt;
    # issue of displaying a report for user RT_System in normal mode, we skip this entirely&lt;br /&gt;
    if ($tr-&amp;amp;gt;CreatorObj-&amp;amp;gt;Name eq &amp;#039;RT_System&amp;#039;) {&lt;br /&gt;
      next;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    # we&amp;#039;ve got some time to account for&lt;br /&gt;
 &lt;br /&gt;
    # is this the first time this person is charging time to this ticket?&lt;br /&gt;
    # if so, add this ticket subject to the data structure&lt;br /&gt;
    if (!exists($stats{$tr-&amp;amp;gt;CreatorObj-&amp;amp;gt;Name}{$t-&amp;amp;gt;id}{Subject})) {&lt;br /&gt;
      $stats{$tr-&amp;amp;gt;CreatorObj-&amp;amp;gt;Name}{$t-&amp;amp;gt;id}{Subject} = $t-&amp;amp;gt;Subject;&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    if ($tr-&amp;amp;gt;TimeTaken != 0) {&lt;br /&gt;
      # this was a comment or correspondence where the user also added some time worked&lt;br /&gt;
      # value of interest appears in Transaction&amp;#039;s TimeTaken column&lt;br /&gt;
      $stats{$tr-&amp;amp;gt;CreatorObj-&amp;amp;gt;Name}{$t-&amp;amp;gt;id}{TimeWorked} += $tr-&amp;amp;gt;TimeTaken;&lt;br /&gt;
    } else {&lt;br /&gt;
      # this was a direct update of the time worked field from the Basics or Jumbo ticket update page&lt;br /&gt;
      # values of interest appear in Transaction&amp;#039;s OldValue and NewValue columns&lt;br /&gt;
      # RT does not use the TimeTaken column in this instance.&lt;br /&gt;
      $stats{$tr-&amp;amp;gt;CreatorObj-&amp;amp;gt;Name}{$t-&amp;amp;gt;id}{TimeWorked} += $tr-&amp;amp;gt;NewValue - $tr-&amp;amp;gt;OldValue;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # report output starts here&lt;br /&gt;
 # output:&lt;br /&gt;
 #  normal user: their own time worked report, most worked ticket to least worked ticket&lt;br /&gt;
 #  superuser:   everyone&amp;#039;s time worked report, in username alpha order, then by most worked to least worked&lt;br /&gt;
 #  superuser+byticket: most worked ticket first, with everyone&amp;#039;s contribution ranked by  biggest contribution to smallest&lt;br /&gt;
 &lt;br /&gt;
 print &amp;quot;&amp;amp;lt;h2&amp;amp;gt;TIME WORKED REPORT FOR QUEUE(S) &amp;quot; . $queuelist . &amp;quot;&amp;amp;lt;/h2&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 print &amp;quot;&amp;amp;lt;h3&amp;amp;gt;Date Range: $startdate TO $enddate&amp;amp;lt;/h3&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 if ($byticket) {&lt;br /&gt;
   print &amp;quot;&amp;amp;lt;h3&amp;amp;gt;Organized by Ticket&amp;amp;lt;/h3&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 print &amp;quot;&amp;amp;lt;hr&amp;amp;gt;&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 # if this person is not a superuser, we should only show them the report for themselves&lt;br /&gt;
 # which means we should remove all keys from %stats except their own username&lt;br /&gt;
 if (!($session{&amp;#039;CurrentUser&amp;#039;}-&amp;amp;gt;HasRight(Right =&amp;amp;gt; &amp;#039;SuperUser&amp;#039;, Object =&amp;amp;gt; $RT::System))) {&lt;br /&gt;
   my %tempstats;&lt;br /&gt;
   $tempstats{$session{CurrentUser}-&amp;amp;gt;Name} = $stats{$session{CurrentUser}-&amp;amp;gt;Name};&lt;br /&gt;
   %stats = %tempstats;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 if ($byticket) {&lt;br /&gt;
   # if we&amp;#039;re going to organize this by ticket, we need to transform the data first&lt;br /&gt;
   # HAVE ENTRIES LIKE:  $stats{JoeUser}{12345}{TimeWorked} = 150&lt;br /&gt;
   #                     $stats{JoeUser}{12345}{Subject} = &amp;quot;Fix the Fubar Widget&amp;quot;&lt;br /&gt;
   # WANT ENTRIES LIKE:  $tstats{12345}{TotalTime} = 250&lt;br /&gt;
   #                     $tstats{12345}{Subject} = &amp;quot;Fix the Fubar Widget&amp;quot;&lt;br /&gt;
   #                     $tstats{12345}{People}{JoeUser} = 150&lt;br /&gt;
   #                     $tstats{12345}{People}{JaneDoe} = 100&lt;br /&gt;
 &lt;br /&gt;
   my %tstats;&lt;br /&gt;
   for my $person (keys %stats) {&lt;br /&gt;
     for my $tid (keys %{$stats{$person}}) {&lt;br /&gt;
       # grab the subject line if you don&amp;#039;t have it already&lt;br /&gt;
       if (!exists($tstats{$tid}{Subject})) {&lt;br /&gt;
         $tstats{$tid}{Subject} = $stats{$person}{$tid}{Subject};&lt;br /&gt;
       }&lt;br /&gt;
       # now increment total time for this ticket&lt;br /&gt;
       $tstats{$tid}{TotalTime} += $stats{$person}{$tid}{TimeWorked};&lt;br /&gt;
       # and record this user&amp;#039;s contribution to this ticket&lt;br /&gt;
       $tstats{$tid}{People}{$person} = $stats{$person}{$tid}{TimeWorked};&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   # Now emit the report&lt;br /&gt;
   for my $tid (sort {$tstats{$b}{TotalTime} &amp;amp;lt;=&amp;amp;gt; $tstats{$a}{TotalTime}} keys %tstats) {&lt;br /&gt;
     my $subject = $tstats{$tid}{Subject};&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;H3&amp;amp;gt;&amp;amp;lt;A TARGET=\&amp;quot;_TimeWorked\&amp;quot; HREF=\&amp;quot;/Ticket/Display.html?id=$tid\&amp;quot;&amp;amp;gt;$tid:  $subject&amp;amp;lt;/A&amp;amp;gt;&amp;amp;lt;/H3&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;TABLE BORDER=0 CELLSPACING=5&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     printf(&amp;quot;&amp;amp;lt;TR&amp;amp;gt;&amp;amp;lt;TH WIDTH=30&amp;amp;gt;&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;%dm&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;%.1fh&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;TOTAL TIME&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;/TR&amp;amp;gt;&amp;quot;,  $tstats{$tid}{TotalTime},($tstats{$tid}{TotalTime} / 60));&lt;br /&gt;
     for my $person (sort {$tstats{$tid}{People}{$b} &amp;amp;lt;=&amp;amp;gt; $tstats{$tid}{People}{$a}} keys %{$tstats{$tid}{People}}) {&lt;br /&gt;
       my $minutes = $tstats{$tid}{People}{$person};&lt;br /&gt;
       printf(&amp;quot;&amp;amp;lt;TR&amp;amp;gt;&amp;amp;lt;TD&amp;amp;gt;&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD&amp;amp;gt;%dm&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD&amp;amp;gt;%.1fh&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD&amp;amp;gt;%s&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;/TR&amp;amp;gt;&amp;quot;,$minutes,($minutes /60),$person);&lt;br /&gt;
     }&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;/TABLE&amp;amp;gt;&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 } else {&lt;br /&gt;
   # the existing %stats data structure is perfect for the default report, no data transform  needed&lt;br /&gt;
   for my $person (sort keys %stats) {&lt;br /&gt;
     # get the person object, so we can get the FriendlyName to use as header&lt;br /&gt;
     my $personobj = new RT::User($session{CurrentUser});&lt;br /&gt;
     $personobj-&amp;amp;gt;Load($person);&lt;br /&gt;
 &lt;br /&gt;
     print &amp;quot;&amp;amp;lt;h3&amp;amp;gt;&amp;quot; . $personobj-&amp;amp;gt;FriendlyName . &amp;quot;&amp;amp;lt;/h3&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;TABLE BORDER=0 CELLSPACING=5&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;TR&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;MINUTES&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;HOURS&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;TH&amp;amp;gt;TICKET&amp;amp;lt;/TH&amp;amp;gt;&amp;amp;lt;/TR&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     my $totalMinutes = 0;&lt;br /&gt;
     for my $tid (sort {$stats{$person}{$b}{TimeWorked} &amp;amp;lt;=&amp;amp;gt; $stats{$person}{$a}{TimeWorked}}  keys %{$stats{$person}}) {&lt;br /&gt;
       my $minutes = $stats{$person}{$tid}{TimeWorked};&lt;br /&gt;
       my $subject = $stats{$person}{$tid}{Subject};&lt;br /&gt;
       print &amp;quot;&amp;amp;lt;TR&amp;amp;gt;&amp;amp;lt;TD ALIGN=RIGHT&amp;amp;gt;${minutes}m&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD ALIGN=RIGHT&amp;amp;gt;&amp;quot; . sprintf(&amp;quot;%.1fh&amp;quot;,($minutes/60)) . &amp;quot;&amp;amp;lt;/TD&amp;amp;gt;&amp;quot; .&lt;br /&gt;
                 &amp;quot;&amp;amp;lt;TD&amp;amp;gt;&amp;amp;lt;A TARGET=\&amp;quot;_TimeWorked\&amp;quot; HREF=\&amp;quot;/Ticket/Display.html?id=$tid\&amp;quot;&amp;amp;gt;$tid:  $subject&amp;amp;lt;/A&amp;amp;gt;&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;/TR&amp;amp;gt;&amp;quot;;&lt;br /&gt;
       $totalMinutes += $minutes;&lt;br /&gt;
     }&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;TR&amp;amp;gt;&amp;amp;lt;TD ALIGN=RIGHT&amp;amp;gt;&amp;amp;lt;B&amp;amp;gt;${totalMinutes}m&amp;amp;lt;/B&amp;amp;gt;&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD ALIGN=RIGHT&amp;amp;gt;&amp;amp;lt;B&amp;amp;gt;&amp;quot; . sprintf(&amp;quot;%.1fh&amp;quot;,($totalMinutes/60)) . &amp;quot;&amp;amp;lt;/B&amp;amp;gt;&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;TD&amp;amp;gt;&amp;amp;lt;B&amp;amp;gt;TOTALS&amp;amp;lt;/B&amp;amp;gt;&amp;amp;lt;/TD&amp;amp;gt;&amp;amp;lt;/TR&amp;amp;gt;&amp;quot;;&lt;br /&gt;
     print &amp;quot;&amp;amp;lt;/TABLE&amp;amp;gt;&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 ##### helper functions below&lt;br /&gt;
 &lt;br /&gt;
 sub form_date_string {&lt;br /&gt;
  # expects seven input params - year, month, day, hour, minute, second, offset&lt;br /&gt;
  my $year = $_[0] - 1900;&lt;br /&gt;
  my $mon = $_[1] - 1;&lt;br /&gt;
  my $day = $_[2];&lt;br /&gt;
  my $hour = $_[3] ? $_[3] : 0;&lt;br /&gt;
  my $min = $_[4] ? $_[4] : 0;&lt;br /&gt;
  my $sec = $_[5] ? $_[5] : 0;&lt;br /&gt;
  my $offset = $_[6] ? $_[6] : 0;&lt;br /&gt;
 &lt;br /&gt;
  # convert to seconds since epoch, then adjust for the $offset, which is also in seconds&lt;br /&gt;
  # we do this so we don&amp;#039;t have to do fancy date arithmetic - we can just subtract one seconds&lt;br /&gt;
  # value from the other seconds value&lt;br /&gt;
  my $starttime = timelocal($sec,$min,$hour,$day,$mon,$year) - $offset;&lt;br /&gt;
 &lt;br /&gt;
  # convert back to component parts now that we&amp;#039;ve adjusted for offset&lt;br /&gt;
  # this gives us the components which represent the GMT time for the local time that was entered&lt;br /&gt;
  # on the command line&lt;br /&gt;
  ($sec,$min,$hour,$day,$mon,$year) = localtime($starttime);&lt;br /&gt;
 &lt;br /&gt;
  # format the date string, padding with zeros if needed&lt;br /&gt;
  return sprintf(&amp;quot;%04d-%02d-%02d %02d:%02d:%02d&amp;quot;, ($year+1900), ($mon+1), $day, $hour, $min, $sec);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;/%perl&amp;amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. Restart your server (unless you are using SetDevelMode, in which case restart is unnecessary).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Much below this line needs cleanup and dates to when this was a standalone CLI script&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;GENERAL IMPLEMENTATION STRATEGY&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
I took a transaction-based approach. I use a SearchBuilder to grab all of the transactions that took place in the time period of interest (see TIME VALUES IN RT / HOW TO SPECIFY DATE RANGES below for time zone issue discussion). I then look at each one and go through the following workflow:&lt;br /&gt;
&lt;br /&gt;
 1. Does this transaction represent a time worked modification?&lt;br /&gt;
    (see INCONSISTENT RECORDING OF TIME WORKED below for issues here)  If no,&lt;br /&gt;
    skip to next transaction.&lt;br /&gt;
 2. Use this transaction&amp;#039;s object ID to retrieve the associated ticket object.&lt;br /&gt;
    If this fails, report the error and skip to next transaction.&lt;br /&gt;
 3. Is this ticket in a queue of interest? If no, skip to next transaction.&lt;br /&gt;
 4. Was this transaction entered by the user RT_System?  If so, it is the result&lt;br /&gt;
    of a merge operation.  Don&amp;#039;t count this time and skip to the next transaction.&lt;br /&gt;
    (The time will be captured elsewhere, under the original user that entered it,&lt;br /&gt;
    if it originally occurred in this time period of interest).&lt;br /&gt;
 &lt;br /&gt;
 Ok, if we got this far, we have real time to account for.&lt;br /&gt;
 &lt;br /&gt;
 5. If this is the first time we are seeing this person for this ticket, create the&lt;br /&gt;
    multilevel data structure to store ticket and time worked info.&lt;br /&gt;
 6. Increment the time worked value (see INCONSISTENT RECORDING OF TIME WORKED below&lt;br /&gt;
    for issues here).&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;TIME VALUES IN RT / HOW TO SPECIFY DATE RANGES&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Internally in the database, RT stores time values as gmtime. This has implications for this script, which are best illustrated by an example.&lt;br /&gt;
&lt;br /&gt;
I live in the US/Central time zone which is -18000 seconds, or -5 hours, off from GM time. I also like to work late at night. If I enter some time worked onto a ticket at 11pm on August 12th, or more formally, at &amp;quot;2009-08-12 23:00:00&amp;quot; in US Central time, that will be entered in the transaction table with a timestamp of &amp;quot;2009-08-13 04:00:00&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Now if I run this script with a startdate of &amp;quot;2009-08-12 00:00:00&amp;quot; and an enddate of &amp;quot;2009-08-12 23:59:59&amp;quot;, I would reasonably expect to get all of the time I worked on August 12th, 2009. However, I would miss the last 5 hours in the day worth of transactions, because RT would have internally shifted the stored timestamp to a time in August 13th (which it already was, over in London!)&lt;br /&gt;
&lt;br /&gt;
So, I assume that users of this script will be entering their time in their local location, and automatically adjust for this. In my case, this means when I enter a start or end date like &amp;quot;2009-08-12 00:00:00&amp;quot;, this script will convert that to &amp;quot;2009-08-12 05:00:00&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Unrelated to this issue but also relevant to the area of time values, MySQL will treat the absence of the HH:MM:SS as 00:00:00.&lt;br /&gt;
&lt;br /&gt;
In sum, if you want all the time worked for a week, let&amp;#039;s say, from Sunday, August 9th through Saturday, August 15th (inclusive), if you use the start and end values &amp;quot;2009-08-09&amp;quot; and &amp;quot;2009-08-16&amp;quot; (Note: 16 not 15!) this script will do the right thing. To be more clear, you might use &amp;quot;2009-08-09&amp;quot; and &amp;quot;2009-08-15 23:59:59&amp;quot;, but I am lazy and don&amp;#039;t mind counting the first second of the 16th as part of the 15th. :-)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;INCONSISTENT RECORDING OF TIME WORKED&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Time can be entered on tickets in two main ways.&lt;br /&gt;
&lt;br /&gt;
 1. Putting a value in the Time Worked field as part of a Comment or Correspondence transaction.&lt;br /&gt;
 2. Directly editing the Time Worked field as part of a Basic or Jumbo ticket update.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Unfortunately, the way that the time gets recorded is different for each scenario.&lt;br /&gt;
&lt;br /&gt;
For scenario 1, in the transaction table the transaction will store the new time worked in the TimeTaken field as minutes.&lt;br /&gt;
&lt;br /&gt;
For scenario 2, in the transaction table the transaction will use the OldValue and NewValue fields to store the old and new values.&lt;br /&gt;
&lt;br /&gt;
So, the script needs to check for both cases, and in scenario 2, has to do a little math to figure out how much time was added.&lt;/div&gt;</summary>
		<author><name>91.196.240.148</name></author>
	</entry>
</feed>