diff options
author | Ivan Kohler <ivan@freeside.biz> | 2015-07-09 17:56:51 -0700 |
---|---|---|
committer | Ivan Kohler <ivan@freeside.biz> | 2015-07-09 17:56:51 -0700 |
commit | d05d7346bb2387fd9d0354923d577275c5c7f019 (patch) | |
tree | fa263fea8fcae20187473ce44ee9829467d513cd | |
parent | 2c09925cad2ade037e6ae953e4ed6fc056811f2f (diff) | |
parent | 9a4a554d471f490b440294eaa9c60000a6db537e (diff) |
Merge branch 'FREESIDE_4_BRANCH' of git.freeside.biz:/home/git/freeside into FREESIDE_4_BRANCH
-rw-r--r-- | FS/FS/Report/Table.pm | 58 | ||||
-rw-r--r-- | FS/FS/cust_main.pm | 2 | ||||
-rw-r--r-- | httemplate/graph/cust_bill_pkg.cgi | 57 | ||||
-rw-r--r-- | httemplate/graph/report_cust_bill_pkg.html | 6 | ||||
-rw-r--r-- | httemplate/misc/email-customer-statement.html | 6 | ||||
-rw-r--r-- | httemplate/misc/email-customers.html | 20 | ||||
-rw-r--r-- | httemplate/misc/process/email-customer-statement.html | 9 | ||||
-rw-r--r-- | httemplate/search/cust_bill_pkg.cgi | 56 | ||||
-rwxr-xr-x | httemplate/search/elements/cust_pay_or_refund.html | 10 | ||||
-rw-r--r-- | httemplate/search/elements/grouped-search/core | 9 | ||||
-rw-r--r-- | httemplate/search/elements/grouped-search/html | 18 | ||||
-rw-r--r-- | httemplate/search/elements/grouped-search/html-print | 4 | ||||
-rw-r--r-- | httemplate/view/cust_main/menu.html | 2 |
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", + "− $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', }, ], [ |