Allow to show estimated, actual and remaining times at once in reports

3col
Vitaliy Filippov 2015-07-13 14:32:13 +03:00
parent b207a79b63
commit 36905704ea
5 changed files with 94 additions and 72 deletions

View File

@ -150,8 +150,10 @@ if (defined($height))
# These shenanigans are necessary to make sure that both vertical and # These shenanigans are necessary to make sure that both vertical and
# horizontal 1D tables convert to the correct dimension when you ask to # horizontal 1D tables convert to the correct dimension when you ask to
# display them as some sort of chart. # display them as some sort of chart.
if (defined $ARGS->{format} && $ARGS->{format} =~ /^(table|simple)$/) my $is_table;
if ($ARGS->{format} eq 'table' || $ARGS->{format} eq 'simple')
{ {
$is_table = 1;
if ($field->{x} && !$field->{y}) if ($field->{x} && !$field->{y})
{ {
# 1D *tables* should be displayed vertically (with a row_field only) # 1D *tables* should be displayed vertically (with a row_field only)
@ -185,14 +187,20 @@ my $measures = {
Bugzilla::Search->COLUMNS->{_count}->{name} = '1'; Bugzilla::Search->COLUMNS->{_count}->{name} = '1';
my $measure = $ARGS->{measure}; my $measure = $ARGS->{measure};
$measure = 'count' unless $measures->{$measure}; if ($measure eq 'times' ? !$is_table : !$measures->{$measure})
{
$measure = 'count';
}
$vars->{measure} = $measure; $vars->{measure} = $measure;
# Validate the values in the axis fields or throw an error. # Validate the values in the axis fields or throw an error.
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;
push @axis_fields, $measures->{$measure} unless $a{$measures->{$measure}}; for ($measure eq 'times' ? qw(etime rtime wtime) : $measure)
{
push @axis_fields, $measures->{$_} unless $a{$measures->{$_}};
}
# Clone the params, so that Bugzilla::Search can modify them # Clone the params, so that Bugzilla::Search can modify them
my $search = new Bugzilla::Search( my $search = new Bugzilla::Search(
@ -205,7 +213,8 @@ $query =
($field->{x} || "''")." x, ". ($field->{x} || "''")." x, ".
($field->{y} || "''")." y, ". ($field->{y} || "''")." y, ".
($field->{z} || "''")." z, ". ($field->{z} || "''")." z, ".
"SUM(".$measures->{$measure}.") r FROM ($query) _report_table GROUP BY ".join(", ", @group_by); join(', ', map { "SUM($measures->{$_}) $_" } $measure eq 'times' ? qw(etime rtime wtime) : $measure).
" FROM ($query) _report_table GROUP BY ".join(", ", @group_by);
$::SIG{TERM} = 'DEFAULT'; $::SIG{TERM} = 'DEFAULT';
$::SIG{PIPE} = 'DEFAULT'; $::SIG{PIPE} = 'DEFAULT';
@ -231,7 +240,7 @@ foreach my $group (@$results)
$isnumeric{$_} &&= ($group->{$_} =~ /^-?\d+(\.\d+)?$/o); $isnumeric{$_} &&= ($group->{$_} =~ /^-?\d+(\.\d+)?$/o);
$names{$_}{$group->{$_}} = 1; $names{$_}{$group->{$_}} = 1;
} }
$data{$group->{z}}{$group->{x}}{$group->{y}} = $group->{r}; $data{$group->{z}}{$group->{x}}{$group->{y}} = $is_table ? $group : $group->{$measure};
} }
my @tbl_names = @{get_names($names{z}, $isnumeric{z}, $field->{z})}; my @tbl_names = @{get_names($names{z}, $isnumeric{z}, $field->{z})};

View File

@ -16,21 +16,21 @@
# Rights Reserved. # Rights Reserved.
# #
# Contributor(s): Gervase Markham <gerv@gerv.net> # Contributor(s): Gervase Markham <gerv@gerv.net>
#
# TODO: Refactor this ugly trash. Table should be generated by code, not by TT.
#%] #%]
[%# INTERFACE: [%# INTERFACE:
# See report-table.html.tmpl. # See report-table.html.tmpl.
#%] #%]
[% colsepchar = user.settings.csv_colsepchar.value %] [% colsepchar = user.settings.csv_colsepchar.value %]
[% num_bugs = BLOCK %]Number of [% terms.bugs %][% END %]
[% tbl_field_disp = field_descs.$tbl_field || Bugzilla.get_field(tbl_field).description || tbl_field %] [% tbl_field_disp = field_descs.$tbl_field || Bugzilla.get_field(tbl_field).description || tbl_field %]
[% col_field_disp = field_descs.$col_field || Bugzilla.get_field(col_field).description || col_field %] [% col_field_disp = field_descs.$col_field || Bugzilla.get_field(col_field).description || col_field %]
[% row_field_disp = field_descs.$row_field || Bugzilla.get_field(row_field).description || row_field %] [% row_field_disp = field_descs.$row_field || Bugzilla.get_field(row_field).description || row_field %]
[% mlist = (measure == 'times' ? [ 'etime', 'wtime', 'rtime' ] : [ measure ]) %]
[% IF tbl_field %] [% IF tbl_field %]
[% IF tbl_field == 'assigned_to' OR tbl_field == 'reporter' [% IF tbl_field == 'assigned_to' OR tbl_field == 'reporter' OR tbl_field == 'qa_contact' %]
OR tbl_field == 'qa_contact'
%]
[% tbl_disp = tbl FILTER email %] [% tbl_disp = tbl FILTER email %]
[% ELSE %] [% ELSE %]
[% tbl_disp = tbl %] [% tbl_disp = tbl %]
@ -45,20 +45,24 @@
[% IF col_field -%] [% IF col_field -%]
[% FOREACH col = col_names -%] [% FOREACH col = col_names -%]
[% colsepchar %] [% colsepchar %]
[% PROCESS value_display value = col field = col_field %] [% PROCESS value_display value=col field=col_field %]
[% END -%] [% END -%]
[% ELSE -%] [% ELSE -%]
[% colsepchar %][% num_bugs FILTER csv %] [% FOR m = mlist %]
[% colsepchar %][% measure_descs.$m | csv %]
[% END %]
[% END %] [% END %]
[% FOREACH row = row_names %] [% FOREACH row = row_names %]
[% PROCESS value_display value = row field = row_field %] [% PROCESS value_display value=row field=row_field %]
[% FOREACH col = col_names %] [% FOREACH col = col_names %]
[% colsepchar %] [% FOREACH m = mlist %]
[% IF data.$tbl AND data.$tbl.$col AND data.$tbl.$col.$row %] [% colsepchar %]
[% data.$tbl.$col.$row -%] [% IF data.$tbl AND data.$tbl.$col AND data.$tbl.$col.$row.$m %]
[% ELSE %] [% data.$tbl.$col.$row.$m -%]
[% -%]0 [% ELSE %]
[% -%]0
[% END %]
[% END %] [% END %]
[% END %] [% END %]
@ -66,9 +70,7 @@
[% BLOCK value_display %] [% BLOCK value_display %]
[% SET disp_value = value %] [% SET disp_value = value %]
[% IF field == 'assigned_to' OR field == 'reporter' [% IF field == 'assigned_to' OR field == 'reporter' OR field == 'qa_contact' %]
OR field == 'qa_contact'
%]
[% disp_value = value FILTER email %] [% disp_value = value FILTER email %]
[% END %] [% END %]
[% disp_value FILTER csv %] [% disp_value FILTER csv %]

View File

@ -71,7 +71,7 @@ END; %]
[% classes = [ [ "t1", "t2" ] , [ "t3", "t4" ] ] %] [% classes = [ [ "t1", "t2" ] , [ "t3", "t4" ] ] %]
[% col_idx = 0 %] [% col_idx = 0 %]
[% row_idx = 0 %] [% row_idx = 0 %]
[% grand_total = 0 %] [% mlist = (measure == 'times' ? [ 'etime', 'wtime', 'rtime' ] : [ measure ]) %]
<table border="1" style="border-collapse: collapse"> <table border="1" style="border-collapse: collapse">
[% IF col_field %] [% IF col_field %]
@ -79,72 +79,77 @@ END; %]
<td class="[% classes.$row_idx.$col_idx %]"> <td class="[% classes.$row_idx.$col_idx %]">
</td> </td>
[% FOREACH col = col_names %] [% FOREACH col = col_names %]
[% col_totals.$col = 0 %]
[% col_idx = 1 - col_idx %] [% col_idx = 1 - col_idx %]
<td class="[% classes.$row_idx.$col_idx %]"> <td class="[% classes.$row_idx.$col_idx %]"[% ' colspan="3"' IF measure == 'times' %]>
[% PROCESS value_display value = col field = col_field %] [% PROCESS value_display value = col field = col_field %]
</td> </td>
[% END %] [% END %]
<td class="ttotal"> <td class="ttotal"[% ' colspan="3"' IF measure == 'times' %]>
Total Total
</td> </td>
</tr> </tr>
[% END %] [% END %]
[% FOREACH row = row_names %] [% FOREACH row = row_names %]
[% row_total = 0 %] [% row_total = {} %]
[% row_idx = 1 - row_idx %] [% row_idx = 1 - row_idx %]
<tr> <tr>
<td class="[% classes.$row_idx.$col_idx %]"> <td class="[% classes.$row_idx.$col_idx %]">
[% PROCESS value_display value = row field = row_field %] [% PROCESS value_display value = row field = row_field %]
</td> </td>
[% FOREACH col = col_names %] [% FOREACH col = col_names %]
[% row_total = row_total + data.$tbl.$col.$row %]
[% col_totals.$col = col_totals.$col + data.$tbl.$col.$row %]
[% col_idx = 1 - col_idx %] [% col_idx = 1 - col_idx %]
<td class="[% classes.$row_idx.$col_idx %]" align="center"> [% FOR m = mlist %]
[% IF data.$tbl.$col.$row AND data.$tbl.$col.$row > 0 %] [% col_totals.$col.$m = col_totals.$col.$m + data.$tbl.$col.$row.$m %]
<a href="[% urlbase %]&amp; [% row_total.$m = row_total.$m + data.$tbl.$col.$row.$m %]
[% PROCESS value_url value=row field=row_field %]&amp; <td class="[% classes.$row_idx.$col_idx %]" align="center">
[% PROCESS value_url value=col field=col_field %]"> [% IF data.$tbl.$col.$row.$m AND data.$tbl.$col.$row.$m > 0 %]
[% data.$tbl.$col.$row %]</a> <a href="[% urlbase %]&amp;
[% ELSE %] [% PROCESS value_url value=row field=row_field %]&amp;
. [% PROCESS value_url value=col field=col_field %]">
[% END %] [% data.$tbl.$col.$row.$m %]</a>
</td> [% END %]
</td>
[% END %]
[% END %]
[% IF col_names.size > 1 %]
[% FOR m = mlist %]
<td class="ttotal" align="right">
<a href="[% urlbase %]&amp;
[% PROCESS value_url value=row field=row_field %]
[% "&amp;$col_vals" IF col_vals %]">
[% row_total.$m %]</a>
[% grand_total.$m = grand_total.$m + row_total.$m %]
</td>
[% END %]
[% END %] [% END %]
<td class="ttotal" align="right">
<a href="[% urlbase %]&amp;
[% PROCESS value_url value=row field=row_field %]
[% "&amp;$col_vals" IF col_vals %]">
[% row_total %]</a>
[% grand_total = grand_total + row_total %]
</td>
</tr> </tr>
[% END %] [% END %]
<tr> <tr>
[% row_idx = 1 - row_idx %] [% row_idx = 1 - row_idx %]
<td class="ttotal"> <td class="ttotal">Total</td>
Total
</td>
[% FOREACH col = col_names %] [% FOREACH col = col_names %]
<td class="ttotal" align="center"> [% FOR m = mlist %]
<a href="[% urlbase %]&amp; <td class="ttotal" align="center">
[% PROCESS value_url value=col field=col_field %] <a href="[% urlbase %]&amp;
[% "&amp;$row_vals" IF row_vals %]"> [% PROCESS value_url value=col field=col_field %]
[% col_totals.$col %]</a> [% "&amp;$row_vals" IF row_vals %]">
</td> [% col_totals.$col.$m %]</a>
</td>
[% END %]
[% END %]
[% IF col_names.size > 1 %]
[% FOR m = mlist %]
<td class="ttotal" align="right">
<strong>
<a href="[% urlbase %]
[% "&amp;$row_vals" IF row_vals %]
[% "&amp;$col_vals" IF col_vals %]">[% grand_total.$m %]</a>
</strong>
</td>
[% END %]
[% END %] [% END %]
<td class="ttotal" align="right">
<strong>
<a href="[% urlbase %]
[% "&amp;$row_vals" IF row_vals %]
[% "&amp;$col_vals" IF col_vals %]">[% grand_total %]</a>
</strong>
</td>
</tr> </tr>
</table> </table>

View File

@ -18,6 +18,11 @@
# Contributor(s): Gervase Markham <gerv@gerv.net> # Contributor(s): Gervase Markham <gerv@gerv.net>
#%] #%]
[% FOREACH tbl = tbl_names %] [% FOREACH tbl = tbl_names %]
[% PROCESS "reports/report-table.csv.tmpl" %] [% measure_descs = {
rtime => 'Remaining time'
[% END %] etime => 'Estimated time'
wtime => 'Actual time'
count => "Number of $terms.bugs"
} %]
[% PROCESS "reports/report-table.csv.tmpl" %]
[% END %]

View File

@ -136,7 +136,7 @@
[% other_format.description FILTER html %] [% other_format.description FILTER html %]
[% "</a>" UNLESS other_format.name == format %] | [% "</a>" UNLESS other_format.name == format %] |
[% END %] [% END %]
<a href="[% formaturl %]&amp;ctype=csv&amp;format=table">CSV</a> <a href="[% formaturl %]&amp;measure=[% measure %]&amp;ctype=csv&amp;format=table">CSV</a>
</td> </td>
[% IF format != "table" %] [% IF format != "table" %]
@ -165,14 +165,15 @@
rtime => 'Remaining time' rtime => 'Remaining time'
etime => 'Estimated time' etime => 'Estimated time'
wtime => 'Actual time' wtime => 'Actual time'
count => 'Bugs count' times => 'Estimated/Actual/Remaining'
count => "Number of $terms.bugs"
} %] } %]
[% FOR m = measure_descs.keys.sort %] [% FOR m = measure_descs.keys.sort %]
[%+ IF measure != m %]<a href="[% formaturl %]&amp;format=[% format %]&amp;measure=[% m %]">[% END %] [% IF m != 'times' || format == 'table' %]
[% measure_descs.$m %] [%+ IF measure != m %]<a href="[% formaturl %]&amp;format=[% format %]&amp;measure=[% m %]">[% END %]
[% IF measure != m %]</a>[% END %] [% measure_descs.$m %]
[% IF NOT loop.last %] [% IF measure != m %]</a>[% END %]
| [% IF NOT loop.last %] | [% END %]
[% END %] [% END %]
[% END %] [% END %]
</td></tr></table> </td></tr></table>