+ return @res;
+ },
+ Function => 'GenerateCustomFieldFunction',
+ Label => sub {
+ my $self = shift;
+ my %args = (@_);
+
+ my ($cf) = ( $args{'SUBKEY'} =~ /^\{(.*)\}$/ );
+ if ( $cf =~ /^\d+$/ ) {
+ my $obj = RT::CustomField->new( $self->CurrentUser );
+ $obj->Load( $cf );
+ $cf = $obj->Name;
+ }
+
+ return 'Custom field [_1]', $cf;
+ },
+ },
+ Enum => {
+ Localize => 1,
+ },
+);
+
+# loc'able strings below generated with (s/loq/loc/):
+# perl -MRT=-init -MRT::Report::Tickets -E 'say qq{\# loq("$_->[0]")} while $_ = splice @RT::Report::Tickets::STATISTICS, 0, 2'
+#
+# loc("Ticket count")
+# loc("Summary of time worked")
+# loc("Total time worked")
+# loc("Average time worked")
+# loc("Minimum time worked")
+# loc("Maximum time worked")
+# loc("Summary of time estimated")
+# loc("Total time estimated")
+# loc("Average time estimated")
+# loc("Minimum time estimated")
+# loc("Maximum time estimated")
+# loc("Summary of time left")
+# loc("Total time left")
+# loc("Average time left")
+# loc("Minimum time left")
+# loc("Maximum time left")
+# loc("Summary of Created-Started")
+# loc("Total Created-Started")
+# loc("Average Created-Started")
+# loc("Minimum Created-Started")
+# loc("Maximum Created-Started")
+# loc("Summary of Created-Resolved")
+# loc("Total Created-Resolved")
+# loc("Average Created-Resolved")
+# loc("Minimum Created-Resolved")
+# loc("Maximum Created-Resolved")
+# loc("Summary of Created-LastUpdated")
+# loc("Total Created-LastUpdated")
+# loc("Average Created-LastUpdated")
+# loc("Minimum Created-LastUpdated")
+# loc("Maximum Created-LastUpdated")
+# loc("Summary of Starts-Started")
+# loc("Total Starts-Started")
+# loc("Average Starts-Started")
+# loc("Minimum Starts-Started")
+# loc("Maximum Starts-Started")
+# loc("Summary of Due-Resolved")
+# loc("Total Due-Resolved")
+# loc("Average Due-Resolved")
+# loc("Minimum Due-Resolved")
+# loc("Maximum Due-Resolved")
+# loc("Summary of Started-Resolved")
+# loc("Total Started-Resolved")
+# loc("Average Started-Resolved")
+# loc("Minimum Started-Resolved")
+# loc("Maximum Started-Resolved")
+
+our @STATISTICS = (
+ COUNT => ['Ticket count', 'Count', 'id'],
+);
+
+foreach my $field (qw(TimeWorked TimeEstimated TimeLeft)) {
+ my $friendly = lc join ' ', split /(?<=[a-z])(?=[A-Z])/, $field;
+ push @STATISTICS, (
+ "ALL($field)" => ["Summary of $friendly", 'TimeAll', $field ],
+ "SUM($field)" => ["Total $friendly", 'Time', 'SUM', $field ],
+ "AVG($field)" => ["Average $friendly", 'Time', 'AVG', $field ],
+ "MIN($field)" => ["Minimum $friendly", 'Time', 'MIN', $field ],
+ "MAX($field)" => ["Maximum $friendly", 'Time', 'MAX', $field ],
+ );
+}
+
+
+foreach my $pair (qw(
+ Created-Started
+ Created-Resolved
+ Created-LastUpdated
+ Starts-Started
+ Due-Resolved
+ Started-Resolved
+)) {
+ my ($from, $to) = split /-/, $pair;
+ push @STATISTICS, (
+ "ALL($pair)" => ["Summary of $pair", 'DateTimeIntervalAll', $from, $to ],
+ "SUM($pair)" => ["Total $pair", 'DateTimeInterval', 'SUM', $from, $to ],
+ "AVG($pair)" => ["Average $pair", 'DateTimeInterval', 'AVG', $from, $to ],
+ "MIN($pair)" => ["Minimum $pair", 'DateTimeInterval', 'MIN', $from, $to ],
+ "MAX($pair)" => ["Maximum $pair", 'DateTimeInterval', 'MAX', $from, $to ],
+ );
+}
+
+our %STATISTICS;
+
+our %STATISTICS_META = (
+ Count => {
+ Function => sub {
+ my $self = shift;
+ my $field = shift || 'id';
+
+ return (
+ FUNCTION => 'COUNT',
+ FIELD => 'id'
+ );
+ },
+ },
+ Simple => {
+ Function => sub {
+ my $self = shift;
+ my ($function, $field) = @_;
+ return (FUNCTION => $function, FIELD => $field);
+ },
+ },
+ Time => {
+ Function => sub {
+ my $self = shift;
+ my ($function, $field) = @_;
+ return (FUNCTION => "$function(?)*60", FIELD => $field);
+ },
+ Display => 'DurationAsString',
+ },
+ TimeAll => {
+ SubValues => sub { return ('Minimum', 'Average', 'Maximum', 'Total') },
+ Function => sub {
+ my $self = shift;
+ my $field = shift;
+ return (
+ Minimum => { FUNCTION => "MIN(?)*60", FIELD => $field },
+ Average => { FUNCTION => "AVG(?)*60", FIELD => $field },
+ Maximum => { FUNCTION => "MAX(?)*60", FIELD => $field },
+ Total => { FUNCTION => "SUM(?)*60", FIELD => $field },
+ );
+ },
+ Display => 'DurationAsString',
+ },
+ DateTimeInterval => {
+ Function => sub {
+ my $self = shift;
+ my ($function, $from, $to) = @_;
+
+ my $interval = $self->_Handle->DateTimeIntervalFunction(
+ From => { FUNCTION => $self->NotSetDateToNullFunction( FIELD => $from ) },
+ To => { FUNCTION => $self->NotSetDateToNullFunction( FIELD => $to ) },
+ );
+
+ return (FUNCTION => "$function($interval)");
+ },
+ Display => 'DurationAsString',
+ },
+ DateTimeIntervalAll => {
+ SubValues => sub { return ('Minimum', 'Average', 'Maximum', 'Total') },
+ Function => sub {
+ my $self = shift;
+ my ($from, $to) = @_;
+
+ my $interval = $self->_Handle->DateTimeIntervalFunction(
+ From => { FUNCTION => $self->NotSetDateToNullFunction( FIELD => $from ) },
+ To => { FUNCTION => $self->NotSetDateToNullFunction( FIELD => $to ) },
+ );
+
+ return (
+ Minimum => { FUNCTION => "MIN($interval)" },
+ Average => { FUNCTION => "AVG($interval)" },
+ Maximum => { FUNCTION => "MAX($interval)" },
+ Total => { FUNCTION => "SUM($interval)" },
+ );
+ },
+ Display => 'DurationAsString',
+ },
+);
+
+sub Groupings {
+ my $self = shift;
+ my %args = (@_);
+
+ my @fields;
+
+ my @tmp = @GROUPINGS;
+ while ( my ($field, $type) = splice @tmp, 0, 2 ) {
+ my $meta = $GROUPINGS_META{ $type } || {};
+ unless ( $meta->{'SubFields'} ) {
+ push @fields, [$field, $field], $field;