From c9081050af4a3bd2d151508605493c946b38ff9d Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Thu, 7 Aug 2014 20:26:43 -0700 Subject: [PATCH] independently change invoice section method and subtotal grouping, #30092 --- FS/FS/Conf.pm | 16 ++++++--- FS/FS/Template_Mixin.pm | 91 ++++++++++++++++++++++++------------------------- FS/FS/Upgrade.pm | 12 +++++++ 3 files changed, 68 insertions(+), 51 deletions(-) diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index c0955b115..8f4d05b3c 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -1561,11 +1561,19 @@ and customer address. Include units.', }, { - 'key' => 'invoice_sections_by_location', + 'key' => 'invoice_sections_method', 'section' => 'invoicing', - 'description' => 'Divide invoice into sections according to service location. Currently, this overrides sectioning by package category.', - 'type' => 'checkbox', - 'per_agent' => 1, + 'description' => 'How to group line items on multi-section invoices.', + 'type' => 'select', + 'select_enum' => [ qw(category location) ], + }, + + { + 'key' => 'summary_subtotals_method', + 'section' => 'invoicing', + 'description' => 'How to group line items when calculating summary subtotals. By default, it will be the same method used for grouping invoice sections.', + 'type' => 'select', + 'select_enum' => [ qw(category location) ], }, #quotations seem broken-ish with sections ATM? diff --git a/FS/FS/Template_Mixin.pm b/FS/FS/Template_Mixin.pm index 07d203036..06b3d9e7b 100644 --- a/FS/FS/Template_Mixin.pm +++ b/FS/FS/Template_Mixin.pm @@ -668,6 +668,8 @@ sub print_generic { $last_bill_balance += $delta; } + $last_bill_balance = sprintf("%.2f", $last_bill_balance); + warn sprintf("LAST BILL: INVNUM %d, DATE %s, BALANCE %.2f\n\n", $last_bill->invnum, $self->time2str_local('%D', $last_bill->_date), @@ -924,7 +926,7 @@ sub print_generic { # we haven't yet changed the template to take advantage of that, so for # now, treat them as mutually exclusive. my %section_method = ( by_category => 1 ); - if ( $conf->exists($tc.'sections_by_location') ) { + if ( $conf->config($tc.'sections_method') eq 'location' ) { %section_method = ( by_location => 1 ); } my ($early, $late) = @@ -982,6 +984,36 @@ sub print_generic { sprintf('%.2f', sum( @charges ) || 0); } + # start setting up summary subtotals + my @summary_subtotals; + my $method = $conf->config('summary_subtotals_method'); + if ( $method and $method ne $conf->config($tc.'sections_method') ) { + # then re-section them by the correct method + my %section_method = ( by_category => 1 ); + if ( $conf->config('summary_subtotals_method') eq 'location' ) { + %section_method = ( by_location => 1 ); + } + my ($early, $late) = + $self->_items_sections( 'summary' => $summarypage, + 'escape' => $escape_function_nonbsp, + 'extra_sections' => $extra_sections, + 'format' => $format, + %section_method + ); + foreach ( @$early ) { + next if $_->{subtotal} == 0; + $_->{subtotal} = $other_money_char.sprintf('%.2f', $_->{subtotal}); + push @summary_subtotals, $_; + } + } else { + # subtotal sectioning is the same as for the actual invoice sections + @summary_subtotals = @sections; + } + + # Hereafter, push sections to both @sections and @summary_subtotals + # if they belong in both places (e.g. tax section). Late sections are + # never in @summary_subtotals. + # previous invoice balances in the Previous Charges section if there # is one, otherwise in the main detail section # (except if summary_only is enabled, don't show them at all) @@ -1084,31 +1116,6 @@ sub print_generic { warn "$me adding line item $line_item\n" if $DEBUG > 1; - # this is silly - #my $detail = { - # ext_description => [], - #}; - #$detail->{'ref'} = $line_item->{'pkgnum'}; - #$detail->{'pkgpart'} = $line_item->{'pkgpart'}; - #$detail->{'quantity'} = $line_item->{'quantity'}; - #$detail->{'section'} = $section; - #$detail->{'description'} = &$escape_function($line_item->{'description'}); - #if ( exists $line_item->{'ext_description'} ) { - # @{$detail->{'ext_description'}} = @{$line_item->{'ext_description'}}; - #} - #$detail->{'amount'} = ( $old_latex ? '' : $money_char ). - # $line_item->{'amount'}; - #if ( exists $line_item->{'unit_amount'} ) { - # $detail->{'unit_amount'} = ( $old_latex ? '' : $money_char ). - # $line_item->{'unit_amount'}; - #} - #$detail->{'product_code'} = $line_item->{'pkgpart'} || 'N/A'; - - #$detail->{'sdate'} = $line_item->{'sdate'}; - #$detail->{'edate'} = $line_item->{'edate'}; - #$detail->{'seconds'} = $line_item->{'seconds'}; - #$detail->{'svc_label'} = $line_item->{'svc_label'}; - #$detail->{'usage_item'} = $line_item->{'usage_item'}; $line_item->{'ref'} = $line_item->{'pkgnum'}; $line_item->{'product_code'} = $line_item->{'pkgpart'} || 'N/A'; # mt()? $line_item->{'section'} = $section; @@ -1145,6 +1152,7 @@ sub print_generic { # if there's anything in the Previous Charges section, prepend it to the list if ( $pr_total and $previous_section ne $default_section ) { unshift @sections, $previous_section; + # but not @summary_subtotals } warn "$me adding taxes\n" @@ -1197,8 +1205,11 @@ sub print_generic { sprintf('%.2f', $taxtotal); $tax_section->{'pretotal'} = 'New charges sub-total '. $total->{'total_amount'}; - push @sections, $tax_section if $taxtotal; - }else{ + if ( $taxtotal ) { + push @sections, $tax_section; + push @summary_subtotals, $tax_section; + } + } else { unshift @total_items, $total; } } @@ -1350,6 +1361,8 @@ sub print_generic { sprintf('%.2f', $adjusttotal); push @sections, $adjust_section unless $adjust_section->{sort_weight}; + # do not summarize; adjustments there are shown according to + # different rules } # create Balance Due message @@ -1428,7 +1441,7 @@ sub print_generic { 'no_subtotal' => 1, }; - push @sections, $discount_section; + push @sections, $discount_section; # do not summarize push @detail_items, map { +{ 'ref' => '', #should this be something else? 'section' => $discount_section, @@ -1438,23 +1451,7 @@ sub print_generic { } } @discounts_avail; } - my @summary_subtotals; - # the templates say "$_->{tax_section} || !$_->{summarized}" - # except 'summarized' is only true when tax_section is true, so this - # is always true, so what's the deal? - foreach my $s (@sections) { - # not to include in the "summary of new charges" block: - # finance charges, adjustments, previous charges, - # and itemized phone usage sections - if ( $s eq $adjust_section or - ($s eq $previous_section and $s ne $default_section) or - ($invoice_data{'finance_section'} and - $invoice_data{'finance_section'} eq $s->{description}) or - $s->{'description'} =~ /^\d+ $/ ) { - next; - } - push @summary_subtotals, $s; - } + # not adding any more sections after this $invoice_data{summary_subtotals} = \@summary_subtotals; # usage subtotals @@ -1462,7 +1459,7 @@ sub print_generic { and $self->can('_items_usage_class_summary') ) { my @usage_subtotals = $self->_items_usage_class_summary(escape => $escape_function); if ( @usage_subtotals ) { - unshift @sections, $usage_subtotals[0]->{section}; + unshift @sections, $usage_subtotals[0]->{section}; # do not summarize unshift @detail_items, @usage_subtotals; } } diff --git a/FS/FS/Upgrade.pm b/FS/FS/Upgrade.pm index ce0e328fd..cb16ead80 100644 --- a/FS/FS/Upgrade.pm +++ b/FS/FS/Upgrade.pm @@ -113,6 +113,18 @@ If you need to continue using the old Form 477 report, turn on the 'old_fcc_report' configuration option. "; } + + # boolean invoice_sections_by_location option is now + # invoice_sections_method = 'location' + my @invoice_sections_confs = + qsearch('conf', { 'name' => { op=>'LIKE', value=>'%sections_by_location' } }); + foreach my $c (@invoice_sections_confs) { + $c->name =~ /^(\w+)sections_by_location$/; + $conf->delete($c->name); + my $newname = $1.'sections_method'; + $conf->set($newname, 'location'); + } + } sub upgrade_overlimit_groups { -- 2.11.0