summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2015-07-09 17:56:51 -0700
committerIvan Kohler <ivan@freeside.biz>2015-07-09 17:56:51 -0700
commitd05d7346bb2387fd9d0354923d577275c5c7f019 (patch)
treefa263fea8fcae20187473ce44ee9829467d513cd
parent2c09925cad2ade037e6ae953e4ed6fc056811f2f (diff)
parent9a4a554d471f490b440294eaa9c60000a6db537e (diff)
Merge branch 'FREESIDE_4_BRANCH' of git.freeside.biz:/home/git/freeside into FREESIDE_4_BRANCH
-rw-r--r--FS/FS/Report/Table.pm58
-rw-r--r--FS/FS/cust_main.pm2
-rw-r--r--httemplate/graph/cust_bill_pkg.cgi57
-rw-r--r--httemplate/graph/report_cust_bill_pkg.html6
-rw-r--r--httemplate/misc/email-customer-statement.html6
-rw-r--r--httemplate/misc/email-customers.html20
-rw-r--r--httemplate/misc/process/email-customer-statement.html9
-rw-r--r--httemplate/search/cust_bill_pkg.cgi56
-rwxr-xr-xhttemplate/search/elements/cust_pay_or_refund.html10
-rw-r--r--httemplate/search/elements/grouped-search/core9
-rw-r--r--httemplate/search/elements/grouped-search/html18
-rw-r--r--httemplate/search/elements/grouped-search/html-print4
-rw-r--r--httemplate/view/cust_main/menu.html2
13 files changed, 166 insertions, 91 deletions
diff --git a/FS/FS/Report/Table.pm b/FS/FS/Report/Table.pm
index eef983d..cba968b 100644
--- a/FS/FS/Report/Table.pm
+++ b/FS/FS/Report/Table.pm
@@ -439,8 +439,8 @@ sub cust_pkg_recur_cost {
=item cust_bill_pkg: the total package charges on invoice line items.
-'charges': limit the type of charges included (setup, recur, usage).
-Should be a string containing one or more of 'S', 'R', or 'U'; if
+'charges': limit the type of charges included (setup, recur, usage, discount).
+Should be a string containing one or more of 'S', 'R', 'U', or 'D'; if
unspecified, defaults to all three.
'classnum': limit to this package class.
@@ -470,6 +470,7 @@ sub cust_bill_pkg {
$sum += $self->cust_bill_pkg_setup(@_) if $charges{S};
$sum += $self->cust_bill_pkg_recur(@_) if $charges{R};
$sum += $self->cust_bill_pkg_detail(@_) if $charges{U};
+ $sum += $self->cust_bill_pkg_discount(@_) if $charges{D};
if ($opt{'average_per_cust_pkg'}) {
my $count = $self->cust_bill_pkg_count_pkgnum(@_);
@@ -656,47 +657,28 @@ sub cust_bill_pkg_detail {
}
sub cust_bill_pkg_discount {
- my( $self, $speriod, $eperiod, $agentnum, %opt ) = @_;
-
- #need to do this the new multi-classnum way if it gets re-enabled
- #my $where = '';
- #my $comparison = '';
- #if ( $opt{'classnum'} =~ /^(\d+)$/ ) {
- # if ( $1 == 0 ) {
- # $comparison = "IS NULL";
- # } else {
- # $comparison = "= $1";
- # }
- #
- # if ( $opt{'use_override'} ) {
- # $where = "(
- # part_pkg.classnum $comparison AND pkgpart_override IS NULL OR
- # override.classnum $comparison AND pkgpart_override IS NOT NULL
- # )";
- # } else {
- # $where = "part_pkg.classnum $comparison";
- # }
- #}
+ my $self = shift;
+ my ($speriod, $eperiod, $agentnum, %opt) = @_;
+ # apply all the same constraints here as for setup/recur
$agentnum ||= $opt{'agentnum'};
- my $total_sql =
- " SELECT COALESCE( SUM( cust_bill_pkg_discount.amount ), 0 ) ";
+ my @where = (
+ '(pkgnum != 0 OR feepart IS NOT NULL)',
+ $self->with_classnum($opt{'classnum'}, $opt{'use_override'}),
+ $self->with_report_option(%opt),
+ $self->in_time_period_and_agent($speriod, $eperiod, $agentnum),
+ $self->with_refnum(%opt),
+ $self->with_cust_classnum(%opt)
+ );
- $total_sql .=
- " FROM cust_bill_pkg_discount
- LEFT JOIN cust_bill_pkg USING ( billpkgnum )
- LEFT JOIN cust_bill USING ( invnum )
- LEFT JOIN cust_main USING ( custnum )
- WHERE ". $self->in_time_period_and_agent($speriod, $eperiod, $agentnum);
- # LEFT JOIN cust_pkg_discount USING ( pkgdiscountnum )
- # LEFT JOIN discount USING ( discountnum )
- # LEFT JOIN cust_pkg USING ( pkgnum )
- # LEFT JOIN part_pkg USING ( pkgpart )
- # LEFT JOIN part_pkg AS override ON pkgpart_override = override.pkgpart
-
- return $self->scalar_sql($total_sql);
+ my $total_sql = "SELECT COALESCE(SUM(cust_bill_pkg_discount.amount), 0)
+ FROM cust_bill_pkg_discount
+ JOIN cust_bill_pkg USING (billpkgnum)
+ $cust_bill_pkg_join
+ WHERE " . join(' AND ', grep $_, @where);
+ $self->scalar_sql($total_sql);
}
##### package churn report #####
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index c6602c1..f55c349 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -4253,6 +4253,8 @@ sub payment_history {
'description' => 'Previous balance',
'amount' => sprintf("%.2f",$previous),
'balance' => sprintf("%.2f",$previous),
+ 'date' => $$opt{'start_date'},
+ 'date_pretty' => $self->time2str_local('short', $$opt{'start_date'} ),
};
#false laziness with above
foreach my $key ( qw(amount balance) ) {
diff --git a/httemplate/graph/cust_bill_pkg.cgi b/httemplate/graph/cust_bill_pkg.cgi
index ea7fee9..b5486f4 100644
--- a/httemplate/graph/cust_bill_pkg.cgi
+++ b/httemplate/graph/cust_bill_pkg.cgi
@@ -27,6 +27,8 @@ my $bottom_link = "$link;";
my $use_usage = $cgi->param('use_usage') || 0;
my $use_setup = $cgi->param('use_setup') || 0;
+my $use_discount = $cgi->param('use_discount') || 2;
+
my $use_override = $cgi->param('use_override') ? 1 : 0;
my $average_per_cust_pkg = $cgi->param('average_per_cust_pkg') ? 1 : 0;
my $distribute = $cgi->param('distribute') ? 1 : 0;
@@ -41,11 +43,13 @@ if ( $average_per_cust_pkg ) {
}
my %charge_labels = (
+ 'SRU'=> 'setup + recurring',
'SR' => 'setup + recurring',
'RU' => 'recurring',
'S' => 'setup',
'R' => 'recurring',
'U' => 'usage',
+ 'D' => 'discount',
);
#XXX or virtual
@@ -186,6 +190,10 @@ elsif ( $use_usage == 2 ) {
$components[-1] =~ s/U//;
}
+if ( $use_discount == 1 ) {
+ push @components, 'D';
+} # else leave discounts off entirely; never combine them with setup/recur
+
# Categorization of line items goes
# Agent -> Referral -> Package class -> Component (setup/recur/usage)
# If per-agent totals are enabled, they go under the Agent level.
@@ -240,21 +248,26 @@ foreach my $agent ( $all_agent || $sel_agent || $FS::CurrentUser::CurrentUser->a
'charges' => $component,
);
- # XXX this is very silly. we should cache it server-side and
- # just put a cache identifier in the link
- my $rowlink = "$link;".
- ($all_agent ? '' : "agentnum=$row_agentnum;").
+ my $row_link = "$link;".
+ "charges=$component;".
+ "distribute=$distribute;";
+
+ if ( $component eq 'D' ) {
+ # discounts ignore 'charges' and 'distribute'
+ $row_link = "${p}search/cust_bill_pkg_discount.html?";
+ }
+
+ $row_link .= ($all_agent ? '' : "agentnum=$row_agentnum;").
($all_part_referral ? '' : "refnum=$row_refnum;").
(join('',map {"cust_classnum=$_;"} @cust_classnums)).
- "distribute=$distribute;".
- "use_override=$use_override;charges=$component;";
- $rowlink .= "$class_param=$_;" foreach @classnums;
+ "use_override=$use_override;";
+ $row_link .= "$class_param=$_;" foreach @classnums;
if ( $all_report_options ) {
push @row_params, 'all_report_options', 1;
- $rowlink .= 'all_report_options=1';
+ $row_link .= 'all_report_options=1';
}
push @params, \@row_params;
- push @links, $rowlink;
+ push @links, $row_link;
@colorbuf = @agent_colors unless @colorbuf;
push @colors, shift @colorbuf;
@@ -293,13 +306,22 @@ foreach my $agent ( $all_agent || $sel_agent || $FS::CurrentUser::CurrentUser->a
($all_part_referral ? () : ('refnum' => $row_refnum)),
'charges' => $component,
);
+
my $row_link = "$link;".
- ($all_agent ? '' : "agentnum=$row_agentnum;").
+ "charges=$component;".
+ "distribute=$distribute;";
+
+ if ( $component eq 'D' ) {
+ # discounts ignore 'charges' and 'distribute'
+ $row_link ="${p}search/cust_bill_pkg_discount.html?";
+ }
+
+ $row_link .= ($all_agent ? '' : "agentnum=$row_agentnum;").
($all_part_referral ? '' : "refnum=$row_refnum;").
(join('',map {"cust_classnum=$_;"} @cust_classnums)).
"$class_param=$row_classnum;".
- "distribute=$distribute;".
- "use_override=$use_override;charges=$component;";
+ "use_override=$use_override;";
+
if ( $class_param eq 'report_optionnum' ) {
push @row_params,
'all_report_options' => 1,
@@ -366,17 +388,6 @@ foreach my $agent ( $all_agent || $sel_agent || $FS::CurrentUser::CurrentUser->a
}
-# may be useful at some point...
-#if ( $average_per_cust_pkg ) {
-# @items = map { ('cust_bill_pkg', 'cust_bill_pkg_count_pkgnum') } @items;
-# @labels = map { $_, "Packages" } @labels;
-# @params = map { $_, $_ } @params;
-# @links = map { $_, $_ } @links;
-# @colors = map { $_, $_ } @colors;
-# @no_graph = map { $_, 1 } @no_graph;
-#}
-#
-
#use Data::Dumper;
if ( $cgi->param('debug') == 1 ) {
$FS::Report::Table::DEBUG = 1;
diff --git a/httemplate/graph/report_cust_bill_pkg.html b/httemplate/graph/report_cust_bill_pkg.html
index 76d3a6c..1db86e3 100644
--- a/httemplate/graph/report_cust_bill_pkg.html
+++ b/httemplate/graph/report_cust_bill_pkg.html
@@ -190,6 +190,12 @@ window.onload = class_mode_changed;
'onchange'=> 'enable_agent_totals',
&>
% }
+<& /elements/tr-select.html,
+ 'label' => 'Discounts',
+ 'field' => 'use_discount',
+ 'options' => [ 1, 2 ],
+ 'labels' => { 1 => 'Separate', 2 => 'Do not show' },
+&>
<TR>
<TD ALIGN="right">Colors</TD>
diff --git a/httemplate/misc/email-customer-statement.html b/httemplate/misc/email-customer-statement.html
index 65660f1..92ce1c4 100644
--- a/httemplate/misc/email-customer-statement.html
+++ b/httemplate/misc/email-customer-statement.html
@@ -5,13 +5,17 @@
'no_search_fields' => [ 'start_date', 'end_date' ],
'alternate_form' => $alternate_form,
'post_search_hook' => $post_search_hook,
+ 'acl' => $acl,
+ 'process_url' => 'process/email-customer-statement.html',
)
%>
<%init>
+my $acl = 'Resend invoices';
+
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
+ unless $FS::CurrentUser::CurrentUser->access_right($acl);
my $alternate_form = sub {
# this could maaaybe be a separate element, for cleanliness
diff --git a/httemplate/misc/email-customers.html b/httemplate/misc/email-customers.html
index 3327303..57f451f 100644
--- a/httemplate/misc/email-customers.html
+++ b/httemplate/misc/email-customers.html
@@ -10,8 +10,12 @@ This may also be used as an element in other pages, enabling you to provide an
alternate initial form while using this for search freezing/thawing and
preview/send actions, with the following options:
+acl - the access right to use (defaults to 'Bulk send customer notices')
+
form_action - the URL to submit the form to
+process_url - the URL for starting the JSRPC process
+
title - the title of the page
no_search_fields - arrayref of additional fields that are not search parameters
@@ -50,7 +54,7 @@ should be used to set msgnum or from/subject/html_body cgi params
<% include('/elements/progress-init.html',
'OneTrueForm',
[ qw( search table from subject html_body text_body msgnum ) ],
- 'process/email-customers.html',
+ $process_url,
$pdest,
)
%>
@@ -90,7 +94,7 @@ should be used to set msgnum or from/subject/html_body cgi params
<INPUT TYPE="hidden" NAME="html_body" VALUE="<% $html_body |h %>">
<TR>
- <TD ALIGN="right" VALIGN="top">Message (HTML display): </TD>
+ <TH ALIGN="right" VALIGN="top">Message (HTML display): </TD>
<TD CLASS="background" ALIGN="left"><% $html_body %></TD>
</TR>
@@ -101,8 +105,11 @@ should be used to set msgnum or from/subject/html_body cgi params
% );
<INPUT TYPE="hidden" NAME="text_body" VALUE="<% $text_body |h %>">
<TR>
- <TD ALIGN="right" VALIGN="top">Message (Text display): </TD>
- <TD CLASS="background" STYLE="background-color:white" ALIGN="left"><PRE><% $text_body %></PRE></TD>
+ <TH ALIGN="right" VALIGN="top">Message (Text display): </TD>
+ <TD CLASS="background" STYLE="background-color:white" ALIGN="left">
+ <a href="javascript:void(0)" onclick="this.style.display='none'; document.getElementById('email-message-text').style.display=''">click to view</a>
+ <PRE id="email-message-text" style="display: none;"><% $text_body %></PRE>
+ </TD>
</TR>
</TABLE>
@@ -192,13 +199,16 @@ Template:
my %opt = @_;
+$opt{'acl'} ||= 'Bulk send customer notices';
+
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('Bulk send customer notices');
+ unless $FS::CurrentUser::CurrentUser->access_right($opt{'acl'});
my $conf = FS::Conf->new;
my @no_search_fields = qw( action table from subject html_body text_body popup url );
my $form_action = $opt{'form_action'} || 'email-customers.html';
+my $process_url = $opt{'process_url'} || 'process/email-customers.html';
my $title = $opt{'title'} || 'Send customer notices';
push( @no_search_fields, @{$opt{'no_search_fields'}} ) if $opt{'no_search_fields'};
diff --git a/httemplate/misc/process/email-customer-statement.html b/httemplate/misc/process/email-customer-statement.html
new file mode 100644
index 0000000..40a8a70
--- /dev/null
+++ b/httemplate/misc/process/email-customer-statement.html
@@ -0,0 +1,9 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices');
+
+my $server = new FS::UI::Web::JSRPC 'FS::cust_main_Mixin::process_email_search_result', $cgi;
+
+</%init>
diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi
index 91fe4e0..6c2cfde 100644
--- a/httemplate/search/cust_bill_pkg.cgi
+++ b/httemplate/search/cust_bill_pkg.cgi
@@ -193,8 +193,8 @@ my $conf = new FS::Conf;
my $money_char = $conf->config('money_char') || '$';
my @select = ( 'cust_bill_pkg.*', 'cust_bill._date' );
-my @total = ( 'COUNT(*)', 'SUM(cust_bill_pkg.setup + cust_bill_pkg.recur)');
-my @total_desc = ( $money_char.'%.2f total' ); # sprintf strings
+my @total = ( 'COUNT(*)' );
+my @total_desc = ();
my @peritem = ( 'setup', 'recur' );
my @peritem_desc = ( 'Setup charges', 'Recurring charges' );
@@ -516,14 +516,32 @@ if ( $cgi->param('nottax') ) {
# setup/recur/usage separation
my %charges = map { $_ => 1 } split('', $cgi->param('charges') || 'SRU');
- if ( $charges{R} and $charges{U} ) {
+ if ( $charges{S} and $charges{R} and $charges{U} ) {
+ # in this case, show discounts
- # default, don't change @peritem or @total
- if ( !$charges{S} ) {
- push @where, 'cust_bill_pkg.recur > 0';
- $total[1] = "SUM(cust_bill_pkg.recur)";
- $total_desc[0] = "$money_char%.2f recurring";
- }
+ $join_pkg .= ' JOIN (
+ SELECT billpkgnum, COALESCE(SUM(amount), 0) AS discounted
+ FROM cust_bill_pkg_discount RIGHT JOIN cust_bill_pkg USING (billpkgnum)
+ GROUP BY billpkgnum
+ ) AS _discount ON (cust_bill_pkg.billpkgnum = _discount.billpkgnum)
+ ';
+ push @select, '_discount.discounted';
+
+ push @peritem, 'discounted';
+ push @peritem_desc, 'Discount';
+ push @total, 'SUM(cust_bill_pkg.setup + cust_bill_pkg.recur + discounted)',
+ 'SUM(discounted)',
+ 'SUM(cust_bill_pkg.setup + cust_bill_pkg.recur)';
+ push @total_desc, "$money_char%.2f gross sales",
+ "&minus; $money_char%.2f discounted",
+ "= $money_char%.2f invoiced";
+
+ } elsif ( $charges{R} and $charges{U} ) {
+
+ # hide rows with no recurring fee, and show the sum of recurring fees only
+ push @where, 'cust_bill_pkg.recur > 0';
+ push @total, "SUM(cust_bill_pkg.recur)";
+ push @total_desc, "$money_char%.2f recurring";
} elsif ( $charges{R} and !$charges{U} ) {
@@ -532,8 +550,8 @@ if ( $cgi->param('nottax') ) {
push @select, "($recur_no_usage) AS recur_no_usage";
$peritem[1] = 'recur_no_usage';
$peritem_desc[1] = 'Recurring charges (excluding usage)';
- $total[1] = "SUM($recur_no_usage)";
- $total_desc[0] = "$money_char%.2f recurring";
+ push @total, "SUM($recur_no_usage)";
+ push @total_desc, "$money_char%.2f recurring";
if ( !$charges{S} ) {
push @where, "($recur_no_usage) > 0";
}
@@ -545,8 +563,8 @@ if ( $cgi->param('nottax') ) {
# there's already a method named 'usage'
$peritem[1] = '_usage';
$peritem_desc[1] = 'Usage charge';
- $total[1] = "SUM($usage)";
- $total_desc[0] = "$money_char%.2f usage charges";
+ push @total, "SUM($usage)";
+ push @total_desc, "$money_char%.2f usage charges";
if ( !$charges{S} ) {
push @where, "($usage) > 0";
}
@@ -554,8 +572,8 @@ if ( $cgi->param('nottax') ) {
} elsif ( $charges{S} ) {
push @where, "cust_bill_pkg.setup > 0";
- $total[1] = "SUM(cust_bill_pkg.setup)";
- $total_desc[0] = "$money_char%.2f setup";
+ push @total, "SUM(cust_bill_pkg.setup)";
+ push @total_desc, "$money_char%.2f setup";
} # else huh? you have to have SOME charges
@@ -578,10 +596,11 @@ if ( $cgi->param('nottax') ) {
}
}
- $total[1] = 'SUM(
+ push @total, 'SUM(
COALESCE(cust_bill_pkg_tax_rate_location.amount,
cust_bill_pkg.setup + cust_bill_pkg.recur)
)';
+ push @total_desc, "$money_char%.2f total";
} else { # the internal-tax case
@@ -591,8 +610,9 @@ if ( $cgi->param('nottax') ) {
';
# don't double-count the components of consolidated taxes
- $total[0] = 'COUNT(DISTINCT cust_bill_pkg.billpkgnum)';
- $total[1] = 'SUM(cust_bill_pkg_tax_location.amount)';
+ @total = ( 'COUNT(DISTINCT cust_bill_pkg.billpkgnum)',
+ 'SUM(cust_bill_pkg_tax_location.amount)' );
+ @total_desc = "$money_char%.2f total";
# package classnum
if ( grep { $_ eq 'classnum' } $cgi->param ) {
diff --git a/httemplate/search/elements/cust_pay_or_refund.html b/httemplate/search/elements/cust_pay_or_refund.html
index ce513ab..5808e5f 100755
--- a/httemplate/search/elements/cust_pay_or_refund.html
+++ b/httemplate/search/elements/cust_pay_or_refund.html
@@ -57,13 +57,14 @@ Examples:
'group_column' => 'payby',
'group_label' => 'payby_name',
- 'subtotal' => { 'paid' => 'sum(paid)' },
+ 'subtotal' => { $opt{name_verb} => "sum($amount_field)" },
'subtotal_row' => [ 'Subtotal',
- sub { sprintf($money, $_[0]->paid) },
+ sub { sprintf($money, $_[0]->$amount_field) },
],
'total_row' => [ '<B>Total</B>',
- sub { sprintf("<B>$money</B>", $_[0]->paid) },
+ sub { sprintf("<B>$money</B>", $_[0]->$amount_field) },
],
+ 'show_combined' => 1,
&>
<%init>
@@ -181,7 +182,7 @@ push @fields, 'payby_payinfo_pretty',
sub { sprintf($money, shift->$amount_field() ) },
;
push @link_onclicks, $sub_receipt, '';
-push @sort_fields, '', $amount_field;
+push @sort_fields, 'paysort', $amount_field;
if ( $unapplied ) {
push @header, emt('Unapplied');
@@ -243,6 +244,7 @@ if ( $cgi->param('magic') ) {
my @search = ();
my @select = (
"$table.*",
+ "( $table.payby || ' ' || coalesce($table.paymask, $table.payinfo) ) AS paysort",
FS::UI::Web::cust_sql_fields(),
'cust_main.custnum AS cust_main_custnum',
);
diff --git a/httemplate/search/elements/grouped-search/core b/httemplate/search/elements/grouped-search/core
index fe47fb7..ffa8cee 100644
--- a/httemplate/search/elements/grouped-search/core
+++ b/httemplate/search/elements/grouped-search/core
@@ -130,6 +130,15 @@ for my $i (0 .. scalar(@groups) - 1) {
push @queries, $detail_query;
}
+if ( $opt{show_combined} ) {
+ # set up group 0 as a combined view
+ unshift @groups, $totals;
+ unshift @group_labels, 'All ' . PL($opt{name_singular}) .
+ ' (' . $totals->num_rows . ')';
+ unshift @group_footers, []; # the total footer will suffice
+ unshift @queries, $base_query->clone;
+}
+
my @total_footer;
if ($opt{'total_row'}) {
for( my $col = 0;
diff --git a/httemplate/search/elements/grouped-search/html b/httemplate/search/elements/grouped-search/html
index aff17ce..df1471a 100644
--- a/httemplate/search/elements/grouped-search/html
+++ b/httemplate/search/elements/grouped-search/html
@@ -71,6 +71,23 @@ for (my $i = 0; $i < $group_info->{num}; $i++) {
push @menubar, $group_info->{group_labels}[$i], ";group=$i";
}
+# not enabled yet; if we need this at some point, enable it on a per-report
+# basis and then disable it for search/cust_pay.html, because it's redundant
+# to see "Check Check #130108", "Credit card Card #401...", etc.
+
+## if this is the combined view, add a column for the group key
+#if ( $curr_group == 0 and $opt{'show_combined'} ) {
+# unshift @{$opt{'header'}}, '';
+# unshift @{$opt{'fields'}}, $opt{group_label};
+# unshift @{$opt{'sort_fields'}}, $opt{group_column} if $opt{'sort_fields'};
+# $opt{'align'} = 'c'.$opt{'align'};
+# foreach (qw(header2 links link_onclicks color size style cell_style xls_format)) {
+# if ( $opt{$_} ) {
+# unshift @{$opt{$_}}, '';
+# }
+# }
+#}
+
</%init>
<& /elements/header.html, $opt{title} &>
@@ -93,6 +110,7 @@ for (my $i = 0; $i < $group_info->{num}; $i++) {
<A HREF="<% $cgi->self_url %>"><% emt('as Excel spreadsheet') %></A><BR>
% $cgi->param('type', 'html-print');
<A HREF="<% $cgi->self_url %>"><% emt('as printable copy') %></A><BR>
+% $cgi->delete('type');
</P>
<% $pager %>
diff --git a/httemplate/search/elements/grouped-search/html-print b/httemplate/search/elements/grouped-search/html-print
index c4c3b1e..6d9521b 100644
--- a/httemplate/search/elements/grouped-search/html-print
+++ b/httemplate/search/elements/grouped-search/html-print
@@ -5,7 +5,9 @@ The "printable" view (all groups on one page).
<%init>
my %opt = @_;
-my $group_info = $m->comp('core', %opt);
+my $group_info = $m->comp('core', %opt,
+ 'show_combined' => 0
+);
my $ncols = scalar(@{ $opt{header} });
my $total_footer = $group_info->{total_footer} || [];
diff --git a/httemplate/view/cust_main/menu.html b/httemplate/view/cust_main/menu.html
index 9486c24..ab56bcf 100644
--- a/httemplate/view/cust_main/menu.html
+++ b/httemplate/view/cust_main/menu.html
@@ -493,7 +493,7 @@ my @menu = (
uri_escape($cgi->self_url);
},
condition => sub { $invoicing_list_emailonly },
- acl => [ 'View invoices', 'Bulk send customer notices' ],
+ acl => 'Resend invoices',
},
],
[