Support numeric fields in reports
parent
bf83ef7a98
commit
0191669861
|
@ -131,6 +131,23 @@ sub _get_names
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub get_measures
|
||||||
|
{
|
||||||
|
my $cols = Bugzilla::Search->REPORT_COLUMNS();
|
||||||
|
my $descs = {
|
||||||
|
count => '',
|
||||||
|
times => '',
|
||||||
|
};
|
||||||
|
for my $f (keys %$cols)
|
||||||
|
{
|
||||||
|
if ($cols->{$f}->{numeric})
|
||||||
|
{
|
||||||
|
$descs->{$f} = $cols->{$f}->{title};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $descs;
|
||||||
|
}
|
||||||
|
|
||||||
sub execute
|
sub execute
|
||||||
{
|
{
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
|
@ -206,24 +223,34 @@ sub execute
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my $measures = {
|
my $measure_alias = {
|
||||||
etime => 'estimated_time',
|
etime => 'estimated_time',
|
||||||
rtime => 'remaining_time',
|
rtime => 'remaining_time',
|
||||||
wtime => 'interval_time',
|
wtime => 'interval_time',
|
||||||
count => '_count',
|
|
||||||
};
|
};
|
||||||
|
my $measures = {
|
||||||
|
count => 'count',
|
||||||
|
};
|
||||||
|
my $old_columns = { %{Bugzilla::Search->COLUMNS($runner)} };
|
||||||
# Trick Bugzilla::Search: replace report columns SQL + add '_count' column
|
# Trick Bugzilla::Search: replace report columns SQL + add '_count' column
|
||||||
# FIXME: Remove usage of global variable COLUMNS in search generation code
|
# FIXME: Remove usage of global variable COLUMNS in search generation code
|
||||||
my %old_columns = %{Bugzilla::Search->COLUMNS($runner)};
|
%{Bugzilla::Search->COLUMNS($runner)} = (%{Bugzilla::Search->COLUMNS($runner)}, %{Bugzilla::Search->REPORT_COLUMNS($runner)});
|
||||||
%{Bugzilla::Search->COLUMNS($runner)} = (%{Bugzilla::Search->COLUMNS($runner)}, %{Bugzilla::Search->REPORT_COLUMNS});
|
Bugzilla::Search->COLUMNS($runner)->{count}->{name} = '1';
|
||||||
Bugzilla::Search->COLUMNS($runner)->{_count}->{name} = '1';
|
my $columns = Bugzilla::Search->COLUMNS($runner);
|
||||||
|
for my $column (keys %$columns)
|
||||||
|
{
|
||||||
|
if ($columns->{$column}->{numeric})
|
||||||
|
{
|
||||||
|
$measures->{$column} = $column;
|
||||||
|
}
|
||||||
|
}
|
||||||
my $measure = $ARGS->{measure} || '';
|
my $measure = $ARGS->{measure} || '';
|
||||||
|
$measure = $measure_alias->{$measure} || $measure;
|
||||||
|
# Check that $measure is available (+ etime/rtime/wtime is usable only in table mode)
|
||||||
if ($measure eq 'times' ? !$is_table : !$measures->{$measure})
|
if ($measure eq 'times' ? !$is_table : !$measures->{$measure})
|
||||||
{
|
{
|
||||||
$measure = 'count';
|
$measure = 'count';
|
||||||
}
|
}
|
||||||
|
|
||||||
# If the user has no access to the measured column, reset it to 'count'
|
# If the user has no access to the measured column, reset it to 'count'
|
||||||
if (!Bugzilla::Search->COLUMNS($runner)->{$measure eq 'times' ? 'remaining_time' : $measures->{$measure}})
|
if (!Bugzilla::Search->COLUMNS($runner)->{$measure eq 'times' ? 'remaining_time' : $measures->{$measure}})
|
||||||
{
|
{
|
||||||
|
@ -234,7 +261,7 @@ sub execute
|
||||||
my %a;
|
my %a;
|
||||||
my @group_by = grep { !($a{$_}++) } values %$field;
|
my @group_by = grep { !($a{$_}++) } values %$field;
|
||||||
my @axis_fields = @group_by;
|
my @axis_fields = @group_by;
|
||||||
for ($measure eq 'times' ? qw(etime rtime wtime) : $measure)
|
for ($measure eq 'times' ? qw(estimated_time remaining_time interval_time) : $measure)
|
||||||
{
|
{
|
||||||
push @axis_fields, $measures->{$_} unless $a{$measures->{$_}};
|
push @axis_fields, $measures->{$_} unless $a{$measures->{$_}};
|
||||||
}
|
}
|
||||||
|
@ -251,7 +278,7 @@ sub execute
|
||||||
($field->{x} || "''")." x, ".
|
($field->{x} || "''")." x, ".
|
||||||
($field->{y} || "''")." y, ".
|
($field->{y} || "''")." y, ".
|
||||||
($field->{z} || "''")." z, ".
|
($field->{z} || "''")." z, ".
|
||||||
join(', ', map { "SUM($measures->{$_}) $_" } $measure eq 'times' ? qw(etime rtime wtime) : $measure).
|
join(', ', map { "SUM($measures->{$_}) $_" } ($measure eq 'times' ? qw(etime rtime wtime) : $measure)).
|
||||||
" FROM ($query) _report_table GROUP BY ".join(", ", @group_by);
|
" FROM ($query) _report_table GROUP BY ".join(", ", @group_by);
|
||||||
|
|
||||||
$::SIG{TERM} = 'DEFAULT';
|
$::SIG{TERM} = 'DEFAULT';
|
||||||
|
@ -264,11 +291,9 @@ sub execute
|
||||||
my %data;
|
my %data;
|
||||||
my %names;
|
my %names;
|
||||||
|
|
||||||
# Read the bug data and count the bugs for each possible value of row, column
|
# Read the bug data and count the bugs for each possible value of row, column and table.
|
||||||
# and table.
|
|
||||||
#
|
#
|
||||||
# We detect a numerical field, and sort appropriately, if all the values are
|
# We detect a numerical field, and sort appropriately, if all the values are numeric.
|
||||||
# numeric.
|
|
||||||
my %isnumeric;
|
my %isnumeric;
|
||||||
|
|
||||||
foreach my $group (@$results)
|
foreach my $group (@$results)
|
||||||
|
@ -369,7 +394,7 @@ sub execute
|
||||||
$vars->{cumulate} = $ARGS->{cumulate} ? 1 : 0;
|
$vars->{cumulate} = $ARGS->{cumulate} ? 1 : 0;
|
||||||
$vars->{x_labels_vertical} = $ARGS->{x_labels_vertical} ? 1 : 0;
|
$vars->{x_labels_vertical} = $ARGS->{x_labels_vertical} ? 1 : 0;
|
||||||
|
|
||||||
%{Bugzilla::Search->COLUMNS($runner)} = %old_columns;
|
%{Bugzilla::Search->COLUMNS($runner)} = %$old_columns;
|
||||||
|
|
||||||
return $vars;
|
return $vars;
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,7 +464,7 @@ sub STATIC_COLUMNS
|
||||||
qa_contact_short => { title => 'QA Contact Login' },
|
qa_contact_short => { title => 'QA Contact Login' },
|
||||||
# FIXME save aggregated work_time in bugs table and search on it
|
# FIXME save aggregated work_time in bugs table and search on it
|
||||||
work_time => { name => $actual_time, numeric => 1 },
|
work_time => { name => $actual_time, numeric => 1 },
|
||||||
interval_time => { name => $actual_time, title => 'Period Worktime', noreports => 1, numeric => 1 },
|
interval_time => { name => $actual_time, title => 'Period Worktime', numeric => 1 },
|
||||||
percentage_complete => {
|
percentage_complete => {
|
||||||
name => "(CASE WHEN $actual_time + bugs.remaining_time = 0.0 THEN 0.0" .
|
name => "(CASE WHEN $actual_time + bugs.remaining_time = 0.0 THEN 0.0" .
|
||||||
" ELSE 100 * ($actual_time / ($actual_time + bugs.remaining_time)) END)",
|
" ELSE 100 * ($actual_time / ($actual_time + bugs.remaining_time)) END)",
|
||||||
|
|
|
@ -51,7 +51,8 @@ my $dbh = Bugzilla->switch_to_shadow_db();
|
||||||
my $action = $ARGS->{action} || 'menu';
|
my $action = $ARGS->{action} || 'menu';
|
||||||
my $token = $ARGS->{token};
|
my $token = $ARGS->{token};
|
||||||
|
|
||||||
if ($action eq "menu")
|
$vars->{measure_descs} = Bugzilla::Report->get_measures();
|
||||||
|
if ($action eq 'menu')
|
||||||
{
|
{
|
||||||
# No need to do any searching in this case, so bail out early.
|
# No need to do any searching in this case, so bail out early.
|
||||||
$template->process("reports/menu.html.tmpl", $vars)
|
$template->process("reports/menu.html.tmpl", $vars)
|
||||||
|
@ -111,7 +112,7 @@ $vars->{report_columns} = Bugzilla::Search->REPORT_COLUMNS();
|
||||||
|
|
||||||
my $formatparam = $ARGS->{format};
|
my $formatparam = $ARGS->{format};
|
||||||
|
|
||||||
if ($action eq "wrap")
|
if ($action eq 'wrap')
|
||||||
{
|
{
|
||||||
# So which template are we using? If action is "wrap", we will be using
|
# So which template are we using? If action is "wrap", we will be using
|
||||||
# no format (it gets passed through to be the format of the actual data),
|
# no format (it gets passed through to be the format of the actual data),
|
||||||
|
|
|
@ -112,7 +112,7 @@ END; %]
|
||||||
<a href="[% urlbase %]&
|
<a href="[% urlbase %]&
|
||||||
[% PROCESS value_url value=row field=row_field %]&
|
[% PROCESS value_url value=row field=row_field %]&
|
||||||
[% PROCESS value_url value=col field=col_field %]">
|
[% PROCESS value_url value=col field=col_field %]">
|
||||||
[% data.$tbl.$col.$row.$m %]</a>
|
[% data.$tbl.$col.$row.$m | format("%.01f") %]</a>
|
||||||
[% END %]
|
[% END %]
|
||||||
</td>
|
</td>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
@ -124,7 +124,7 @@ END; %]
|
||||||
<a href="[% urlbase %]&
|
<a href="[% urlbase %]&
|
||||||
[% PROCESS value_url value=row field=row_field %]
|
[% PROCESS value_url value=row field=row_field %]
|
||||||
[% "&$col_vals" IF col_vals %]">
|
[% "&$col_vals" IF col_vals %]">
|
||||||
[% row_total.$m %]</a>
|
[% row_total.$m | format("%.01f") %]</a>
|
||||||
[% grand_total.$m = grand_total.$m + row_total.$m %]
|
[% grand_total.$m = grand_total.$m + row_total.$m %]
|
||||||
</td>
|
</td>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
@ -142,7 +142,7 @@ END; %]
|
||||||
<a href="[% urlbase %]&
|
<a href="[% urlbase %]&
|
||||||
[% PROCESS value_url value=col field=col_field %]
|
[% PROCESS value_url value=col field=col_field %]
|
||||||
[% "&$row_vals" IF row_vals %]">
|
[% "&$row_vals" IF row_vals %]">
|
||||||
[% col_totals.$col_n.$m %]</a>
|
[% col_totals.$col_n.$m | format("%.01f") %]</a>
|
||||||
</td>
|
</td>
|
||||||
[% END %]
|
[% END %]
|
||||||
[% col_n = col_n + 1 %]
|
[% col_n = col_n + 1 %]
|
||||||
|
@ -153,7 +153,7 @@ END; %]
|
||||||
<strong>
|
<strong>
|
||||||
<a href="[% urlbase %]
|
<a href="[% urlbase %]
|
||||||
[% "&$row_vals" IF row_vals %]
|
[% "&$row_vals" IF row_vals %]
|
||||||
[% "&$col_vals" IF col_vals %]">[% grand_total.$m %]</a>
|
[% "&$col_vals" IF col_vals %]">[% grand_total.$m | format("%.01f") %]</a>
|
||||||
</strong>
|
</strong>
|
||||||
</td>
|
</td>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
|
@ -139,13 +139,8 @@
|
||||||
Show:
|
Show:
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
[% measure_descs = {
|
[% measure_descs.times = 'Estimated/Actual/Remaining' %]
|
||||||
rtime => 'Remaining time'
|
[% measure_descs.count = "Number of $terms.bugs" %]
|
||||||
etime => 'Estimated time'
|
|
||||||
wtime => 'Actual time'
|
|
||||||
times => 'Estimated/Actual/Remaining'
|
|
||||||
count => "Number of $terms.bugs"
|
|
||||||
} %]
|
|
||||||
<select name="measure" style="width: 100%; border: 0; margin-top: 2px">
|
<select name="measure" style="width: 100%; border: 0; margin-top: 2px">
|
||||||
[% FOR m = measure_descs.keys.sort %]
|
[% FOR m = measure_descs.keys.sort %]
|
||||||
<option value="[% m %]"[% IF measure == m %] selected="selected"[% END %]>[% measure_descs.$m %]</option>
|
<option value="[% m %]"[% IF measure == m %] selected="selected"[% END %]>[% measure_descs.$m %]</option>
|
||||||
|
|
Loading…
Reference in New Issue