independently change invoice section method and subtotal grouping, #30092
authorMark Wells <mark@freeside.biz>
Fri, 8 Aug 2014 03:26:22 +0000 (20:26 -0700)
committerMark Wells <mark@freeside.biz>
Fri, 8 Aug 2014 03:26:53 +0000 (20:26 -0700)
FS/FS/Conf.pm
FS/FS/Template_Mixin.pm
FS/FS/Upgrade.pm

index 5ed78c9..35b88ea 100644 (file)
@@ -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?
index 07d2030..06b3d9e 100644 (file)
@@ -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;
     }
   }
index db24215..a7be5c8 100644 (file)
@@ -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 {