Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Move activity reports code into elements.

Allow saving reports to SavedSearch with type of ActivityReport.
Thunk the portlet display api to show saved reports.
  • Loading branch information...
commit 858c48c3ecbcaedd241085110cdece0f96831873 1 parent 0d83e3d
Chia-liang Kao authored
View
55 html/Reports/Activity/ActivitySummary.html
@@ -2,59 +2,6 @@
path => "Reports/Activity/ActivitySummary.html",
&>
-<& Elements/MiniPlot, data => \%queues &>
+<& Elements/ActivitySummary, %ARGS &>
-<table style="width: 100%">
-<tr class="titlerow">
-<th>Queue</th>
-% for my $status (sort keys %status) {
-<th><% $status %></th>
-% }
-<th>Total</th>
-</tr>
-% for my $queue (sort keys %queues) {
-<th class="label"><% $queue %></th>
-% for my $status (sort keys %status) {
-<td><% $queues{$queue}{$status} || 0 %>
-% }
-<td><% $total{$queue} %></td>
-</tr>
-% }
-<tr class="grandtotal">
-<th class="label" >Grand Total</th>
-% for my $status (sort keys %status) {
-<td><% $status{$status} %></td>
-% }
-<td><% $total %></td>
-</table>
</&>
-<%args>
-$query => ''
-$start => "2005/01/01"
-$end => "2006/01/01"
-</%args>
-<%init>
-my $tickets = RT::Tickets->new($session{'CurrentUser'});
-$tickets->FromSQL(join " AND ", map {"($_)"} grep {/\S/} ($query, "Updated >= '$start' AND Updated <= '$end'"));
-
-my %queues;
-my %status;
-my %total;
-my $total;
-while (my $ticket = $tickets->Next) {
- my $txns = $ticket->Transactions;
- $txns->Limit(FIELD => 'Created', OPERATOR => '>=', VALUE => $start);
- $txns->Limit(FIELD => 'Created', OPERATOR => '<=', VALUE => $end);
- $txns->Limit(FIELD => 'Type', VALUE => 'Status', ENTRYAGGREGATOR => 'OR');
- $txns->Limit(FIELD => 'Type', VALUE => 'Create');
-
- while (my $txn = $txns->Next) {
- $queues{$txn->TicketObj->QueueObj->Name}{$txn->NewValue || 'new'}++;
- $status{$txn->NewValue || 'new'}++;
- $total{$txn->TicketObj->QueueObj->Name}++;
- $total++;
- }
-}
-
-
-</%init>
View
57 html/Reports/Activity/Elements/ActivitySummary
@@ -0,0 +1,57 @@
+
+<& MiniPlot, data => \%queues &>
+
+<table style="width: 100%">
+<tr class="titlerow">
+<th>Queue</th>
+% for my $status (sort keys %status) {
+<th><% $status %></th>
+% }
+<th>Total</th>
+</tr>
+% for my $queue (sort keys %queues) {
+<th class="label"><% $queue %></th>
+% for my $status (sort keys %status) {
+<td><% $queues{$queue}{$status} || 0 %>
+% }
+<td><% $total{$queue} %></td>
+</tr>
+% }
+<tr class="grandtotal">
+<th class="label" >Grand Total</th>
+% for my $status (sort keys %status) {
+<td><% $status{$status} %></td>
+% }
+<td><% $total %></td>
+</table>
+
+<%args>
+$query => ''
+$start => "2005/01/01"
+$end => "2006/01/01"
+</%args>
+<%init>
+my $tickets = RT::Tickets->new($session{'CurrentUser'});
+$tickets->FromSQL(join " AND ", map {"($_)"} grep {/\S/} ($query, "Updated >= '$start' AND Updated <= '$end'"));
+
+my %queues;
+my %status;
+my %total;
+my $total;
+while (my $ticket = $tickets->Next) {
+ my $txns = $ticket->Transactions;
+ $txns->Limit(FIELD => 'Created', OPERATOR => '>=', VALUE => $start);
+ $txns->Limit(FIELD => 'Created', OPERATOR => '<=', VALUE => $end);
+ $txns->Limit(FIELD => 'Type', VALUE => 'Status', ENTRYAGGREGATOR => 'OR');
+ $txns->Limit(FIELD => 'Type', VALUE => 'Create');
+
+ while (my $txn = $txns->Next) {
+ $queues{$txn->TicketObj->QueueObj->Name}{$txn->NewValue || 'new'}++;
+ $status{$txn->NewValue || 'new'}++;
+ $total{$txn->TicketObj->QueueObj->Name}++;
+ $total++;
+ }
+}
+
+
+</%init>
View
2  html/Reports/Activity/Elements/LimitReport
@@ -1,4 +1,4 @@
-<form action="index.html" method="POST" enctype="multipart/form-data">
+<form action="index.html" method="GET">
Query:
<textarea name="query" rows="5" cols="80"><% $query %></textarea><br />
View
60 html/Reports/Activity/Elements/ResolutionComments
@@ -0,0 +1,60 @@
+
+<table style="width: 100%">
+<tr>
+<th>Queue</th><th>Ticket #</th><th>Created</th><th>Resolved</th><th>Time to resolve</th>
+</tr>
+<tr>
+<th colspan="5">Resolution comments</th>
+</tr>
+% for my $item (@items) {
+<tr class="titlerow">
+<td><% $item->{queue} %></td>
+<td><% $item->{id} %></td>
+<td><% $item->{created} %></td>
+<td><% $item->{resolved} %></td>
+<td><% $item->{duration} %></td>
+</tr>
+<tr>
+<td colspan="5"><% $item->{whiteboard} %></td>
+</tr>
+% }
+</table>
+
+<%args>
+$query => ''
+$start => "2005/01/01"
+$end => "2006/01/01"
+</%args>
+<%init>
+
+use Time::Duration;
+
+my $summary_tickets = RT::Tickets->new( $session{'CurrentUser'} );
+$summary_tickets->FromSQL(
+ join " AND ", map {"($_)"} grep {/\S/} ($query, "(Status = 'resolved') AND ( Updated >= '$start' AND Updated <= '$end')"));
+
+my @items;
+while ( my $ticket = $summary_tickets->Next ) {
+ my $whiteboard = $ticket->CustomFieldValues('Whiteboard') ?
+ $ticket->FirstCustomFieldValue('Whiteboard') : undef;
+ push @items, {
+ queue => $ticket->QueueObj->Name,
+ id => $ticket->id,
+ created => $ticket->CreatedObj->AsString,
+ resolved => $ticket->ResolvedObj->AsString,
+ duration => Time::Duration::concise(
+ Time::Duration::duration(
+ $ticket->ResolvedObj->Unix - $ticket->CreatedObj->Unix
+ )
+ ),
+ whiteboard => $whiteboard,
+ };
+}
+
+@items = sort { $a->{queue} cmp $b->{queue} || $a->{id} <=> $b->{id} } @items;
+
+
+
+
+
+</%init>
View
91 html/Reports/Activity/Elements/ResolutionStatistics
@@ -0,0 +1,91 @@
+
+<& MiniPlot,
+ data => \%plot,
+ major => ['Date range','Last 30 days','Last 60 days','Last 90 days','Ever'],
+ minor => [(sort keys %queues), "Average"]
+ &>
+
+<table style="width: 100%">
+<tr>
+<td></td><th colspan="4">Number of tickets closed / Average resolution time per ticket</th>
+</tr>
+<tr class="titlerow">
+<th>Queue</th>
+<th>Date range</th>
+<th>Last 30 days</th>
+<th>Last 60 days</th>
+<th>Last 90 days</th>
+<th>Ever</th>
+</tr>
+% for my $queue (sort keys %queues) {
+<tr>
+<th><% $queue %></th>
+% for my $period ('Date range','Last 30 days','Last 60 days','Last 90 days','Ever') {
+<td><% scalar @{$closed{$period}{$queue} || []} %> / <% $average_resolve_times{$period}{$queue} %></td>
+% }
+</tr>
+% }
+<tr class="grandtotal">
+<th>Ticket average</th>
+% for my $period ('Date range','Last 30 days','Last 60 days','Last 90 days','Ever') {
+<td><% $average_resolve_times{$period}{_all_count} %> / <% $average_resolve_times{$period}{_all} %></td>
+% }
+</tr>
+</table>
+
+<%args>
+$query => ''
+$start => "2005/01/01"
+$end => "2006/01/01"
+</%args>
+<%init>
+
+my $in_30_days = RT::Date->new($session{'CurrentUser'});
+$in_30_days->Set(Format => 'Unix', Value => ( time - (86400*30)));
+my $in_60_days = RT::Date->new($session{'CurrentUser'});
+$in_60_days->Set(Format => 'Unix', Value => ( time - (86400*60)));
+my $in_90_days = RT::Date->new($session{'CurrentUser'});
+$in_90_days->Set(Format => 'Unix', Value => ( time - (86400*90)));
+
+my %queries;
+$queries{'Date range'} = "(Resolved >= '$start' AND Resolved <= '$end')";
+$queries{'Last 30 days'} = "(Resolved >= '".$in_30_days->ISO."')";
+$queries{'Last 60 days'} = "(Resolved >= '".$in_60_days->ISO."')";
+$queries{'Last 90 days'} = "(Resolved >= '".$in_90_days->ISO."')";
+$queries{'Ever'} = "(Status = 'resolved' OR Status = 'rejected')";
+
+
+my %closed;
+my %queues;
+foreach my $period (keys %queries) {
+ my $tix = RT::Tickets->new($session{'CurrentUser'});
+ $tix->FromSQL(join " AND ", map {"($_)"} grep {/\S/} ($query, $queries{$period}));
+
+ while (my $ticket = $tix->Next) {
+ push @{ $closed{$period}{$ticket->QueueObj->Name}}, $ticket;
+ $queues{$ticket->QueueObj->Name}++;
+ }
+}
+
+my %restimes;
+my %average_resolve_times;
+my %plot;
+use Time::Duration;
+foreach my $period ( keys %closed ) {
+ foreach my $queue ( keys %{$closed{$period}} ) {
+ foreach my $ticket (@{$closed{$period}{$queue}} ) {
+ push @{$restimes{$period}{$queue}}, ( $ticket->ResolvedObj->Unix - $ticket->CreatedObj->Unix);
+ }
+
+ my $total_time = 0;
+ $total_time+= $_ for @{$restimes{$period}{$queue}};
+ $average_resolve_times{$period}{'_all_time'} += $total_time;
+ $average_resolve_times{$period}{'_all_count'} += @{$restimes{$period}{$queue}};
+ $plot{$period}{$queue} = $total_time / @{$restimes{$period}{$queue}};
+ $average_resolve_times{$period}{$queue} = Time::Duration::concise(Time::Duration::duration($plot{$period}{$queue}));
+ }
+ $plot{$period}{Average} = $average_resolve_times{$period}{'_all_time'} / $average_resolve_times{$period}{'_all_count'};
+ $average_resolve_times{$period}{'_all'} = Time::Duration::concise(Time::Duration::duration($plot{$period}{Average}));
+}
+
+</%init>
View
194 html/Reports/Activity/Elements/WorkedStatistics
@@ -0,0 +1,194 @@
+
+<& MiniPlot, data => \%plot, minor => ["< 24h","24-48h","> 48h"] &>
+
+<br />
+<table class="numberreport">
+<tr class="titlerow">
+<th rowspan="2">Queue</th>
+<th colspan="6">Created in date range</th>
+<th colspan="6">Resolved in date range</th>
+<th rowspan="2">Total tickets still open</th>
+</tr>
+<tr class="titlerow">
+<th>Total tickets</th>
+<th>Total resolutions</th>
+<th>Resolved within 24h</th>
+<th>Resolved within 24-48h</th>
+<th>Resolved in more than 48h</th>
+<th>Tickets currently open</th>
+
+<th>Total tickets</th>
+<th>Total resolutions</th>
+<th>Resolved within 24h</th>
+<th>Resolved within 24-48h</th>
+<th>Resolved in more than 48h</th>
+<th>Tickets currently open</th>
+</tr>
+
+% my @totals;
+% for my $queue (sort {lc $queue{$a}{name} cmp lc $queue{$b}{name}} keys %queue) {
+% my @row; my $i = 0;
+<tr>
+<th><% $queue{$queue}{name} %></th>
+% for my $bin (qw/created resolved/) {
+<td><% $row[$i++] = $queue{$queue}{$bin}{tickets} || 0%></td>
+<td><% $row[$i++] = $queue{$queue}{$bin}{resolves} || 0%></td>
+<td><% $row[$i++] = $queue{$queue}{$bin}{24} || 0 %></td>
+<td><% $row[$i++] = $queue{$queue}{$bin}{48} || 0 %></td>
+<td><% $row[$i++] = $queue{$queue}{$bin}{more} || 0 %></td>
+<td><% $row[$i++] = $queue{$queue}{$bin}{open} || 0 %></td>
+% }
+
+<td><% $row[$i++] = $queue{$queue}{total_open} %></td>
+</tr>
+% $totals[$_] += $row[$_] for 0..$#row;
+% }
+<tr class="grandtotal">
+<th>Total</th>
+% for (@totals) {
+<td><% $_ %></td>
+% }
+</tr>
+</table>
+
+<br />
+<table class="numberreport">
+<tr class="titlerow">
+<th>Username</th>
+<th>Queue</th>
+<th>Resolved within 24h</th>
+<th>Resolved within 24-28h</th>
+<th>Resolved in more than 48h</th>
+<th>Time worked</th>
+<th>Average time per ticket</th>
+<th>Average resolutions per hour</th>
+</tr>
+% for my $user (sort keys %user) {
+% for my $queue (sort {lc $queue{$a}{name} cmp lc $queue{$b}{name}} keys %{$user{$user}}) {
+<tr>
+<th><% $user %></th>
+<th><% $queue{$queue}{name} %></th>
+<td><% $user{$user}{$queue}{24} || 0 %></td>
+<td><% $user{$user}{$queue}{48} || 0 %></td>
+<td><% $user{$user}{$queue}{more} || 0 %></td>
+<td><% sprintf("%.02f",$user{$user}{$queue}{time}/60 || 0) %></td>
+<td><% sprintf("%.02f",$user{$user}{$queue}{time}/(scalar keys %{$user{$user}{$queue}{tickets}}) || 0) %></td>
+<td><% $user{$user}{$queue}{time} ? sprintf("%.02f",$user{$user}{$queue}{resolves}/($user{$user}{$queue}{time}/60) || 0) : "-" %></td>
+</tr>
+% }
+% }
+</table>
+
+<br />
+<h3>Still open tickets created in date range</h3>
+<& /Elements/TicketList,
+ Query => qq{ ( Created >= '$start' AND Created <= '$end' ) AND ( Status = 'new' OR Status = 'open' ) },
+ OrderBy => 'Created',
+ Order => 'ASC',
+ Format => q{' <b><a href="/Ticket/Display.html?id=__id__">__id__</a></b>/TITLE:#','<a href="/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject','__QueueName__','__Created__'},
+ Rows => 0,
+ BaseURL => $RT::WebPath."/Search/Results.html?",
+ AllowSorting => 1,
+&>
+<br />
+
+<%args>
+$query => ""
+$start => "2005/01/01"
+$end => "2006/01/01"
+</%args>
+<%init>
+my $startDate = RT::Date->new($session{'CurrentUser'});
+$startDate->Set(Format => 'unknown', Value => $start);
+my $endDate = RT::Date->new($session{'CurrentUser'});
+$endDate->Set(Format => 'unknown', Value => $end);
+
+my(%queue, %user);
+my $Queues = RT::Queues->new($session{'CurrentUser'});
+$Queues->UnLimit();
+while (my $queue = $Queues->Next) {
+ my $tix = RT::Tickets->new($session{'CurrentUser'});
+ $tix->FromSQL("Queue = '@{[$queue->Name]}' AND (Status = 'open' OR Status = 'new')");
+ $queue{$queue->Id}{name} = $queue->Name;
+ $queue{$queue->Id}{total_open} = $tix->Count();
+}
+
+my $tix = RT::Tickets->new($session{'CurrentUser'});
+$tix->FromSQL(join " AND ", map {"($_)"} grep {/\S/} ($query, "Updated >= '$start' AND Updated <= '$end'"));
+while (my $ticket = $tix->Next) {
+ my $created = $ticket->CreatedObj;
+ my $resolved = $ticket->ResolvedObj;
+
+ $RT::Logger->debug("Looking at ticket @{[$ticket->id]}");
+
+ # "bin" is either "created" and/or "resolved"; it could be neither.
+ my %bins;
+ $bins{created} = 1 if $created->Unix > $startDate->Unix and $created->Unix < $endDate->Unix;
+
+ # Find out when we *first* responded to this ticket
+ my $opened = $created;
+ my $txns = $ticket->Transactions;
+ while (my $txn = $txns->Next) {
+ $RT::Logger->debug( " TXN: @{[$txn->Created]}" );
+ # Abort when we hit transactions after our end date
+ last if $txn->CreatedObj->Unix > $endDate->Unix;
+
+ if (not $opened and $txn->Type eq "Status" and $txn->NewValue =~ /new|open/) {
+ # As each one goes by, notice when tickets pop open
+ $opened = $txn->CreatedObj;
+ } elsif ($opened and $txn->Type eq "Status" and $txn->NewValue eq "resolved") {
+ # Or are resolved
+ if ($txn->CreatedObj->Unix >= $startDate->Unix) {
+ # We only *really* care about it when it was resolved
+ # in the date range. Now this counts in the "resolved
+ # in range" bin, possibly in addition to "created in
+ # range" bin.
+ $bins{resolved} = 1;
+
+ # Figure out which "time to resolve" bucket it goes
+ # in. Buckets aren't bins! Bucket is time to resolve
+ # a ticket. Bin is if the ticket was created or
+ # resolved at all in the time range.
+ my $time = $txn->CreatedObj->Diff($opened);
+ $time = ($time < 24*60*60 ? "24" : ($time < 48*60*60 ? "48" : "more"));
+
+ # Keep track of resolves,resolves per time bucket, and tickets for each bin
+ $queue{$ticket->Queue}{$_}{$time}++ for keys %bins;
+ $queue{$ticket->Queue}{$_}{resolves}++ for keys %bins;
+ # Tickets per bin is done at the end
+
+ # Also for the creator-queue combo
+ $user{$txn->CreatorObj->Name}{$ticket->Queue}{$time}++;
+ $user{$txn->CreatorObj->Name}{$ticket->Queue}{resolves}++;
+ $user{$txn->CreatorObj->Name}{$ticket->Queue}{tickets}{$ticket->Id}++;
+ }
+ # Forget when we were opened
+ undef $opened;
+ }
+
+ if ($txn->TimeTaken and $txn->CreatedObj->Unix >= $startDate->Unix) {
+ # If this txn has some time taken, and is in the target
+ # range, record it.
+ $queue{$ticket->Queue}{time} += $txn->TimeTaken;
+ $user{$txn->CreatorObj->Name}{$ticket->Queue}{time} += $txn->TimeTaken;
+ $user{$txn->CreatorObj->Name}{$ticket->Queue}{tickets}{$ticket->Id}++;
+ }
+ }
+
+ # If we cared about this ticket in any way..
+ for my $bin (keys %bins) {
+ # Record the number of open and total tickets for each bin.
+ $queue{$ticket->Queue}{$bin}{tickets}++;
+ $queue{$ticket->Queue}{$bin}{open}++ if $ticket->Status =~ /new|open/;
+ }
+}
+
+my %plot;
+for (keys %queue) {
+ $plot{$queue{$_}{name}} = {
+ "< 24h" => $queue{$_}{resolved}{24},
+ "24-48h" => $queue{$_}{resolved}{48},
+ "> 48h" => $queue{$_}{resolved}{more},
+ };
+}
+</%init>
View
60 html/Reports/Activity/ResolutionComments.html
@@ -2,63 +2,5 @@
path => "Reports/Activity/ResolutionComments.html",
&>
-<table style="width: 100%">
-<tr>
-<th>Queue</th><th>Ticket #</th><th>Created</th><th>Resolved</th><th>Time to resolve</th>
-</tr>
-<tr>
-<th colspan="5">Resolution comments</th>
-</tr>
-% for my $item (@items) {
-<tr class="titlerow">
-<td><% $item->{queue} %></td>
-<td><% $item->{id} %></td>
-<td><% $item->{created} %></td>
-<td><% $item->{resolved} %></td>
-<td><% $item->{duration} %></td>
-</tr>
-<tr>
-<td colspan="5"><% $item->{whiteboard} %></td>
-</tr>
-% }
-</table>
+<& Elements/ResolutionComments, %ARGS &>
</&>
-
-<%args>
-$query => ''
-$start => "2005/01/01"
-$end => "2006/01/01"
-</%args>
-<%init>
-
-use Time::Duration;
-
-my $summary_tickets = RT::Tickets->new( $session{'CurrentUser'} );
-$summary_tickets->FromSQL(
- join " AND ", map {"($_)"} grep {/\S/} ($query, "(Status = 'resolved') AND ( Updated >= '$start' AND Updated <= '$end')"));
-
-my @items;
-while ( my $ticket = $summary_tickets->Next ) {
- my $whiteboard = $ticket->CustomFieldValues('Whiteboard') ?
- $ticket->FirstCustomFieldValue('Whiteboard') : undef;
- push @items, {
- queue => $ticket->QueueObj->Name,
- id => $ticket->id,
- created => $ticket->CreatedObj->AsString,
- resolved => $ticket->ResolvedObj->AsString,
- duration => Time::Duration::concise(
- Time::Duration::duration(
- $ticket->ResolvedObj->Unix - $ticket->CreatedObj->Unix
- )
- ),
- whiteboard => $whiteboard,
- };
-}
-
-@items = sort { $a->{queue} cmp $b->{queue} || $a->{id} <=> $b->{id} } @items;
-
-
-
-
-
-</%init>
View
91 html/Reports/Activity/ResolutionStatistics.html
@@ -2,94 +2,5 @@
path => "Reports/Activity/ResolutionStatistics.html",
&>
-<& Elements/MiniPlot,
- data => \%plot,
- major => ['Date range','Last 30 days','Last 60 days','Last 90 days','Ever'],
- minor => [(sort keys %queues), "Average"]
- &>
-
-<table style="width: 100%">
-<tr>
-<td></td><th colspan="4">Number of tickets closed / Average resolution time per ticket</th>
-</tr>
-<tr class="titlerow">
-<th>Queue</th>
-<th>Date range</th>
-<th>Last 30 days</th>
-<th>Last 60 days</th>
-<th>Last 90 days</th>
-<th>Ever</th>
-</tr>
-% for my $queue (sort keys %queues) {
-<tr>
-<th><% $queue %></th>
-% for my $period ('Date range','Last 30 days','Last 60 days','Last 90 days','Ever') {
-<td><% scalar @{$closed{$period}{$queue} || []} %> / <% $average_resolve_times{$period}{$queue} %></td>
-% }
-</tr>
-% }
-<tr class="grandtotal">
-<th>Ticket average</th>
-% for my $period ('Date range','Last 30 days','Last 60 days','Last 90 days','Ever') {
-<td><% $average_resolve_times{$period}{_all_count} %> / <% $average_resolve_times{$period}{_all} %></td>
-% }
-</tr>
-</table>
-
+<& Elements/Statistics, %ARGS &>
</&>
-<%args>
-$query => ''
-$start => "2005/01/01"
-$end => "2006/01/01"
-</%args>
-<%init>
-
-my $in_30_days = RT::Date->new($session{'CurrentUser'});
-$in_30_days->Set(Format => 'Unix', Value => ( time - (86400*30)));
-my $in_60_days = RT::Date->new($session{'CurrentUser'});
-$in_60_days->Set(Format => 'Unix', Value => ( time - (86400*60)));
-my $in_90_days = RT::Date->new($session{'CurrentUser'});
-$in_90_days->Set(Format => 'Unix', Value => ( time - (86400*90)));
-
-my %queries;
-$queries{'Date range'} = "(Resolved >= '$start' AND Resolved <= '$end')";
-$queries{'Last 30 days'} = "(Resolved >= '".$in_30_days->ISO."')";
-$queries{'Last 60 days'} = "(Resolved >= '".$in_60_days->ISO."')";
-$queries{'Last 90 days'} = "(Resolved >= '".$in_90_days->ISO."')";
-$queries{'Ever'} = "(Status = 'resolved' OR Status = 'rejected')";
-
-
-my %closed;
-my %queues;
-foreach my $period (keys %queries) {
- my $tix = RT::Tickets->new($session{'CurrentUser'});
- $tix->FromSQL(join " AND ", map {"($_)"} grep {/\S/} ($query, $queries{$period}));
-
- while (my $ticket = $tix->Next) {
- push @{ $closed{$period}{$ticket->QueueObj->Name}}, $ticket;
- $queues{$ticket->QueueObj->Name}++;
- }
-}
-
-my %restimes;
-my %average_resolve_times;
-my %plot;
-use Time::Duration;
-foreach my $period ( keys %closed ) {
- foreach my $queue ( keys %{$closed{$period}} ) {
- foreach my $ticket (@{$closed{$period}{$queue}} ) {
- push @{$restimes{$period}{$queue}}, ( $ticket->ResolvedObj->Unix - $ticket->CreatedObj->Unix);
- }
-
- my $total_time = 0;
- $total_time+= $_ for @{$restimes{$period}{$queue}};
- $average_resolve_times{$period}{'_all_time'} += $total_time;
- $average_resolve_times{$period}{'_all_count'} += @{$restimes{$period}{$queue}};
- $plot{$period}{$queue} = $total_time / @{$restimes{$period}{$queue}};
- $average_resolve_times{$period}{$queue} = Time::Duration::concise(Time::Duration::duration($plot{$period}{$queue}));
- }
- $plot{$period}{Average} = $average_resolve_times{$period}{'_all_time'} / $average_resolve_times{$period}{'_all_count'};
- $average_resolve_times{$period}{'_all'} = Time::Duration::concise(Time::Duration::duration($plot{$period}{Average}));
-}
-
-</%init>
View
194 html/Reports/Activity/WorkedStatistics.html
@@ -2,197 +2,5 @@
path => "Reports/Activity/WorkedStatistics.html",
&>
-<& Elements/MiniPlot, data => \%plot, minor => ["< 24h","24-48h","> 48h"] &>
-
-<br />
-<table class="numberreport">
-<tr class="titlerow">
-<th rowspan="2">Queue</th>
-<th colspan="6">Created in date range</th>
-<th colspan="6">Resolved in date range</th>
-<th rowspan="2">Total tickets still open</th>
-</tr>
-<tr class="titlerow">
-<th>Total tickets</th>
-<th>Total resolutions</th>
-<th>Resolved within 24h</th>
-<th>Resolved within 24-48h</th>
-<th>Resolved in more than 48h</th>
-<th>Tickets currently open</th>
-
-<th>Total tickets</th>
-<th>Total resolutions</th>
-<th>Resolved within 24h</th>
-<th>Resolved within 24-48h</th>
-<th>Resolved in more than 48h</th>
-<th>Tickets currently open</th>
-</tr>
-
-% my @totals;
-% for my $queue (sort {lc $queue{$a}{name} cmp lc $queue{$b}{name}} keys %queue) {
-% my @row; my $i = 0;
-<tr>
-<th><% $queue{$queue}{name} %></th>
-% for my $bin (qw/created resolved/) {
-<td><% $row[$i++] = $queue{$queue}{$bin}{tickets} || 0%></td>
-<td><% $row[$i++] = $queue{$queue}{$bin}{resolves} || 0%></td>
-<td><% $row[$i++] = $queue{$queue}{$bin}{24} || 0 %></td>
-<td><% $row[$i++] = $queue{$queue}{$bin}{48} || 0 %></td>
-<td><% $row[$i++] = $queue{$queue}{$bin}{more} || 0 %></td>
-<td><% $row[$i++] = $queue{$queue}{$bin}{open} || 0 %></td>
-% }
-
-<td><% $row[$i++] = $queue{$queue}{total_open} %></td>
-</tr>
-% $totals[$_] += $row[$_] for 0..$#row;
-% }
-<tr class="grandtotal">
-<th>Total</th>
-% for (@totals) {
-<td><% $_ %></td>
-% }
-</tr>
-</table>
-
-<br />
-<table class="numberreport">
-<tr class="titlerow">
-<th>Username</th>
-<th>Queue</th>
-<th>Resolved within 24h</th>
-<th>Resolved within 24-28h</th>
-<th>Resolved in more than 48h</th>
-<th>Time worked</th>
-<th>Average time per ticket</th>
-<th>Average resolutions per hour</th>
-</tr>
-% for my $user (sort keys %user) {
-% for my $queue (sort {lc $queue{$a}{name} cmp lc $queue{$b}{name}} keys %{$user{$user}}) {
-<tr>
-<th><% $user %></th>
-<th><% $queue{$queue}{name} %></th>
-<td><% $user{$user}{$queue}{24} || 0 %></td>
-<td><% $user{$user}{$queue}{48} || 0 %></td>
-<td><% $user{$user}{$queue}{more} || 0 %></td>
-<td><% sprintf("%.02f",$user{$user}{$queue}{time}/60 || 0) %></td>
-<td><% sprintf("%.02f",$user{$user}{$queue}{time}/(scalar keys %{$user{$user}{$queue}{tickets}}) || 0) %></td>
-<td><% $user{$user}{$queue}{time} ? sprintf("%.02f",$user{$user}{$queue}{resolves}/($user{$user}{$queue}{time}/60) || 0) : "-" %></td>
-</tr>
-% }
-% }
-</table>
-
-<br />
-<h3>Still open tickets created in date range</h3>
-<& /Elements/TicketList,
- Query => qq{ ( Created >= '$start' AND Created <= '$end' ) AND ( Status = 'new' OR Status = 'open' ) },
- OrderBy => 'Created',
- Order => 'ASC',
- Format => q{' <b><a href="/Ticket/Display.html?id=__id__">__id__</a></b>/TITLE:#','<a href="/Ticket/Display.html?id=__id__">__Subject__</a>/TITLE:Subject','__QueueName__','__Created__'},
- Rows => 0,
- BaseURL => $RT::WebPath."/Search/Results.html?",
- AllowSorting => 1,
-&>
-<br />
-
+<& Elements/WorkedStatistics, %ARGS &>
</&>
-<%args>
-$query => ""
-$start => "2005/01/01"
-$end => "2006/01/01"
-</%args>
-<%init>
-my $startDate = RT::Date->new($session{'CurrentUser'});
-$startDate->Set(Format => 'unknown', Value => $start);
-my $endDate = RT::Date->new($session{'CurrentUser'});
-$endDate->Set(Format => 'unknown', Value => $end);
-
-my(%queue, %user);
-my $Queues = RT::Queues->new($session{'CurrentUser'});
-$Queues->UnLimit();
-while (my $queue = $Queues->Next) {
- my $tix = RT::Tickets->new($session{'CurrentUser'});
- $tix->FromSQL("Queue = '@{[$queue->Name]}' AND (Status = 'open' OR Status = 'new')");
- $queue{$queue->Id}{name} = $queue->Name;
- $queue{$queue->Id}{total_open} = $tix->Count();
-}
-
-my $tix = RT::Tickets->new($session{'CurrentUser'});
-$tix->FromSQL(join " AND ", map {"($_)"} grep {/\S/} ($query, "Updated >= '$start' AND Updated <= '$end'"));
-while (my $ticket = $tix->Next) {
- my $created = $ticket->CreatedObj;
- my $resolved = $ticket->ResolvedObj;
-
- $RT::Logger->debug("Looking at ticket @{[$ticket->id]}");
-
- # "bin" is either "created" and/or "resolved"; it could be neither.
- my %bins;
- $bins{created} = 1 if $created->Unix > $startDate->Unix and $created->Unix < $endDate->Unix;
-
- # Find out when we *first* responded to this ticket
- my $opened = $created;
- my $txns = $ticket->Transactions;
- while (my $txn = $txns->Next) {
- $RT::Logger->debug( " TXN: @{[$txn->Created]}" );
- # Abort when we hit transactions after our end date
- last if $txn->CreatedObj->Unix > $endDate->Unix;
-
- if (not $opened and $txn->Type eq "Status" and $txn->NewValue =~ /new|open/) {
- # As each one goes by, notice when tickets pop open
- $opened = $txn->CreatedObj;
- } elsif ($opened and $txn->Type eq "Status" and $txn->NewValue eq "resolved") {
- # Or are resolved
- if ($txn->CreatedObj->Unix >= $startDate->Unix) {
- # We only *really* care about it when it was resolved
- # in the date range. Now this counts in the "resolved
- # in range" bin, possibly in addition to "created in
- # range" bin.
- $bins{resolved} = 1;
-
- # Figure out which "time to resolve" bucket it goes
- # in. Buckets aren't bins! Bucket is time to resolve
- # a ticket. Bin is if the ticket was created or
- # resolved at all in the time range.
- my $time = $txn->CreatedObj->Diff($opened);
- $time = ($time < 24*60*60 ? "24" : ($time < 48*60*60 ? "48" : "more"));
-
- # Keep track of resolves,resolves per time bucket, and tickets for each bin
- $queue{$ticket->Queue}{$_}{$time}++ for keys %bins;
- $queue{$ticket->Queue}{$_}{resolves}++ for keys %bins;
- # Tickets per bin is done at the end
-
- # Also for the creator-queue combo
- $user{$txn->CreatorObj->Name}{$ticket->Queue}{$time}++;
- $user{$txn->CreatorObj->Name}{$ticket->Queue}{resolves}++;
- $user{$txn->CreatorObj->Name}{$ticket->Queue}{tickets}{$ticket->Id}++;
- }
- # Forget when we were opened
- undef $opened;
- }
-
- if ($txn->TimeTaken and $txn->CreatedObj->Unix >= $startDate->Unix) {
- # If this txn has some time taken, and is in the target
- # range, record it.
- $queue{$ticket->Queue}{time} += $txn->TimeTaken;
- $user{$txn->CreatorObj->Name}{$ticket->Queue}{time} += $txn->TimeTaken;
- $user{$txn->CreatorObj->Name}{$ticket->Queue}{tickets}{$ticket->Id}++;
- }
- }
-
- # If we cared about this ticket in any way..
- for my $bin (keys %bins) {
- # Record the number of open and total tickets for each bin.
- $queue{$ticket->Queue}{$bin}{tickets}++;
- $queue{$ticket->Queue}{$bin}{open}++ if $ticket->Status =~ /new|open/;
- }
-}
-
-my %plot;
-for (keys %queue) {
- $plot{$queue{$_}{name}} = {
- "< 24h" => $queue{$_}{resolved}{24},
- "24-48h" => $queue{$_}{resolved}{48},
- "> 48h" => $queue{$_}{resolved}{more},
- };
-}
-</%init>
View
57 html/Reports/Activity/index.html
@@ -1,5 +1,22 @@
<&| Elements/Wrapper, %ARGS, title => loc("Activity reports"), show_print_link => 0 &>
+% if ($type) {
+<form method="post" action="index.html" name="SaveChart">
+
+<& /Search/Elements/SelectSearchObject, Name => 'Owner', Objects => \@Objects &><br />
+
+<&|/l&>Description</&>:<br>
+<font size="-1"><input size="25" name="Description" value="" /></font>
+<input type="hidden" class="hidden" name="query" value="<% $query %>" />
+<input type="hidden" class="hidden" name="start" value="<% $start %>" />
+<input type="hidden" class="hidden" name="end" value="<% $end %>" />
+<input type="hidden" class="hidden" name="type" value="<% $type %>" />
+
+<input type="submit" name="Save" value="<%loc('Save')%>" class="button" />
+</form>
+
+<& /Search/Elements/ActivityReport, Query => $query, Start => $start, End => $end, ReportType => $type &>
+% }
</&>
@@ -8,6 +25,7 @@
$start => undef
$end => undef
$query => undef
+$Description => undef
</%args>
<%init>
unless ($start) {
@@ -22,7 +40,42 @@
$ARGS{end} = substr($now->ISO,0,10);
}
-if ($type) {
- $m->redirect($type . ".html?" . $m->comp('/Elements/QueryString', query => $query, start => $start, end => $end));
+my @Objects;
+
+push @Objects, $session{CurrentUser}->UserObj;
+
+my $groups = RT::Groups->new($session{'CurrentUser'});
+
+$groups->LimitToUserDefinedGroups;
+$groups->WithMember(PrincipalId => $session{'CurrentUser'}->Id,
+ Recursively => 1);
+
+push (@Objects, @{$groups->ItemsArrayRef()});
+push @Objects, RT::System->new($session{'CurrentUser'})
+ if $session{'CurrentUser'}->HasRight( Object=> $RT::System,
+ Right => 'SuperUser');
+
+if ( $ARGS{Save} ) {
+ if ( $ARGS{'Owner'} =~ /^(.*?)-(\d+)$/ ) {
+ # We're saving a new search
+ my $obj_type = $1;
+ my $obj_id = $2;
+ # Find out if we're saving on the user, or a group
+ my $container_object = _load_container_object( $obj_type, $obj_id );
+ my ( $search_id, $search_msg ) = $container_object->AddAttribute(
+ Name => 'SavedSearch',
+ Description => $Description,
+ Content => {
+ SearchType => 'ActivityReport',
+ Query => $query,
+ ReportType => $type,
+ Start => $start,
+ End => $end,
+
+ }
+ );
+
+ }
}
+
</%init>
View
9 html/Search/ActivityReport.html
@@ -0,0 +1,9 @@
+<%args>
+$ReportType => undef
+$Start => undef
+$End => undef
+$Query => undef
+</%args>
+<%init>
+$m->redirect('/Reports/Activity/index.html?' . $m->comp('/Elements/QueryString', query => $Query, start => $Start, end => $End, type => $ReportType));
+</%init>
View
7 html/Search/Elements/ActivityReport
@@ -0,0 +1,7 @@
+<%args>
+$ReportType => undef
+$Start => undef
+$End => undef
+$Query => undef
+</%args>
+<& '/Reports/Activity/Elements/'.$ReportType, start => $Start, end => $End, query => $Query &>
View
2  lib/RT/Extension/ActivityReports.pm
@@ -1,3 +1,3 @@
package RT::Extension::ActivityReports;
-our $VERSION = '0.4';
+our $VERSION = '0.5';
Please sign in to comment.
Something went wrong with that request. Please try again.