[freeside-commits] branch FREESIDE_3_BRANCH updated. 60f71e8b94fcd4403ad59c0508de59f90eb6edc5
Mark Wells
mark at 420.am
Wed Feb 4 21:39:19 PST 2015
The branch, FREESIDE_3_BRANCH has been updated
via 60f71e8b94fcd4403ad59c0508de59f90eb6edc5 (commit)
from 745e36b35b36607f450d16944469f52e362bf934 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 60f71e8b94fcd4403ad59c0508de59f90eb6edc5
Author: Mark Wells <mark at freeside.biz>
Date: Wed Feb 4 21:12:56 2015 -0800
allow fees to be grouped with taxes on the invoice, #32223
diff --git a/FS/FS/Template_Mixin.pm b/FS/FS/Template_Mixin.pm
index d46f617..61e708e 100644
--- a/FS/FS/Template_Mixin.pm
+++ b/FS/FS/Template_Mixin.pm
@@ -7,7 +7,7 @@ use vars qw( $DEBUG $me
);
# but NOT $conf
use vars qw( $invoice_lines @buf ); #yuck
-use List::Util qw(sum);
+use List::Util qw(sum first);
use Date::Format;
use Date::Language;
use Text::Template 1.20;
@@ -908,29 +908,6 @@ sub print_generic {
warn "$me generating sections\n"
if $DEBUG > 1;
- my $taxtotal = 0;
- my $tax_section = { 'description' => $self->mt('Taxes, Surcharges, and Fees'),
- 'subtotal' => $taxtotal, # adjusted below
- 'tax_section' => 1,
- };
- my $tax_weight = _pkg_category($tax_section->{description})
- ? _pkg_category($tax_section->{description})->weight
- : 0;
- $tax_section->{'summarized'} = ''; #why? $summarypage && !$tax_weight ? 'Y' : '';
- $tax_section->{'sort_weight'} = $tax_weight;
-
- my $adjusttotal = 0;
- my $adjust_section = {
- 'description' => $self->mt('Credits, Payments, and Adjustments'),
- 'adjust_section' => 1,
- 'subtotal' => 0, # adjusted below
- };
- my $adjust_weight = _pkg_category($adjust_section->{description})
- ? _pkg_category($adjust_section->{description})->weight
- : 0;
- $adjust_section->{'summarized'} = ''; #why? $summarypage && !$adjust_weight ? 'Y' : '';
- $adjust_section->{'sort_weight'} = $adjust_weight;
-
my $unsquelched = $params{unsquelch_cdr} || $cust_main->squelch_cdr ne 'Y';
my $multisection = $conf->exists($tc.'sections', $cust_main->agentnum) ||
$conf->exists($tc.'sections_by_location', $cust_main->agentnum);
@@ -971,6 +948,21 @@ sub print_generic {
$previous_section = $default_section;
}
+ my $adjust_section = {
+ 'description' => $self->mt('Credits, Payments, and Adjustments'),
+ 'adjust_section' => 1,
+ 'subtotal' => 0, # adjusted below
+ };
+ my $adjust_weight = _pkg_category($adjust_section->{description})
+ ? _pkg_category($adjust_section->{description})->weight
+ : 0;
+ $adjust_section->{'summarized'} = ''; #why? $summarypage && !$adjust_weight ? 'Y' : '';
+ # Note: 'sort_weight' here is actually a flag telling whether there is an
+ # explicit package category for the adjust section. If so, certain behavior
+ # happens.
+ $adjust_section->{'sort_weight'} = $adjust_weight;
+
+
if ( $multisection ) {
($extra_sections, $extra_lines) =
$self->_items_extra_usage_sections($escape_function_nonbsp, $format)
@@ -1220,6 +1212,26 @@ sub print_generic {
warn "$me adding taxes\n"
if $DEBUG > 1;
+ # create a tax section if we don't yet have one
+ my $tax_description = 'Taxes, Surcharges, and Fees';
+ my $tax_section = first { $_->{description} eq $tax_description } @sections;
+ if (!$tax_section) {
+ $tax_section = { 'description' => $tax_description };
+ push @sections, $tax_section if $multisection;
+ }
+ $tax_section->{tax_section} = 1; # mark this section as containing taxes
+ # if this is an existing tax section, we're merging the tax items into it.
+ # grab the taxtotal that's already there, strip the money symbol if any
+ my $taxtotal = $tax_section->{'subtotal'} || 0;
+ $taxtotal =~ s/^\Q$other_money_char\E//;
+
+ # this does nothing
+ #my $tax_weight = _pkg_category($tax_section->{description})
+ # ? _pkg_category($tax_section->{description})->weight
+ # : 0;
+ #$tax_section->{'summarized'} = ''; #why? $summarypage && !$tax_weight ? 'Y' : '';
+ #$tax_section->{'sort_weight'} = $tax_weight;
+
my @items_tax = $self->_items_tax;
foreach my $tax ( @items_tax ) {
@@ -1262,14 +1274,20 @@ sub print_generic {
$other_money_char. sprintf('%.2f', $self->charged - $taxtotal );
if ( $multisection ) {
- $tax_section->{'subtotal'} = $other_money_char.
- sprintf('%.2f', $taxtotal);
- $tax_section->{'pretotal'} = 'New charges sub-total '.
- $total->{'total_amount'};
- if ( $taxtotal ) {
- push @sections, $tax_section;
- push @summary_subtotals, $tax_section;
+ if ( $taxtotal > 0 ) {
+ $tax_section->{'subtotal'} = $other_money_char.
+ sprintf('%.2f', $taxtotal);
+ $tax_section->{'pretotal'} = 'New charges sub-total '.
+ $total->{'total_amount'};
+ $tax_section->{'description'} = $self->mt($tax_description);
+
+ # append it if it's not already there
+ if ( !grep $tax_section, @sections ) {
+ push @sections, $tax_section;
+ push @summary_subtotals, $tax_section;
+ }
}
+
} else {
unshift @total_items, $total;
}
@@ -1285,7 +1303,6 @@ sub print_generic {
$money_char. sprintf("%10.2f",$self->charged) ];
push @buf,['',''];
-
###
# Totals
###
@@ -1361,7 +1378,6 @@ sub print_generic {
$total->{'total_item'} = &$escape_function($credit->{'description'});
$credittotal += $credit->{'amount'};
$total->{'total_amount'} = $minus.$other_money_char.$credit->{'amount'};
- $adjusttotal += $credit->{'amount'};
if ( $multisection ) {
push @detail_items, {
ext_description => [],
@@ -1395,7 +1411,6 @@ sub print_generic {
$total->{'total_item'} = &$escape_function($payment->{'description'});
$paymenttotal += $payment->{'amount'};
$total->{'total_amount'} = $minus.$other_money_char.$payment->{'amount'};
- $adjusttotal += $payment->{'amount'};
if ( $multisection ) {
push @detail_items, {
ext_description => [],
@@ -1417,7 +1432,10 @@ sub print_generic {
if ( $multisection ) {
$adjust_section->{'subtotal'} = $other_money_char.
- sprintf('%.2f', $adjusttotal);
+ sprintf('%.2f', $credittotal + $paymenttotal);
+
+ #why this? because {sort_weight} forces the adjust_section to appear
+ #in @extra_sections instead of @sections. obviously.
push @sections, $adjust_section
unless $adjust_section->{sort_weight};
# do not summarize; adjustments there are shown according to
@@ -2794,11 +2812,16 @@ equivalent to
$self->_items_cust_bill_pkg([ $self->cust_bill_pkg ])
-The only OPTIONS accepted is 'section', which may point to a hashref
-with a key named 'condensed', which may have a true value. If it
-does, this method tries to merge identical items into items with
-'quantity' equal to the number of items (not the sum of their
-separate quantities, for some reason).
+OPTIONS are passed through to _items_cust_bill_pkg, and should include
+'format' and 'escape_function' at minimum.
+
+To produce items for a specific invoice section, OPTIONS should include
+'section', a hashref containing 'category' and/or 'locationnum' keys.
+
+'section' may also contain a key named 'condensed'. If this is present
+and has a true value, _items_pkg will try to merge identical items into items
+with 'quantity' equal to the number of items (not the sum of their separate
+quantities, for some reason).
=cut
@@ -2866,13 +2889,14 @@ sub _items_fee {
}
foreach (sort keys(%base_invnums)) {
next if $_ == $self->invnum;
+ # per convention, we must escape ext_description lines
push @ext_desc,
&{$escape_function}(
$self->mt('from invoice #[_1] on [_2]', $_, $base_invnums{$_})
);
}
my $desc = $part_fee->itemdesc_locale($self->cust_main->locale);
- $desc = &{$escape_function}($desc);
+ # but not escape the base description line
push @items,
{ feepart => $cust_bill_pkg->feepart,
diff --git a/FS/FS/cust_bill_pkg_tax_location.pm b/FS/FS/cust_bill_pkg_tax_location.pm
index 140982e..f16e930 100644
--- a/FS/FS/cust_bill_pkg_tax_location.pm
+++ b/FS/FS/cust_bill_pkg_tax_location.pm
@@ -124,7 +124,7 @@ sub check {
|| $self->ut_foreign_key('billpkgnum', 'cust_bill_pkg', 'billpkgnum' )
|| $self->ut_number('taxnum') #cust_bill_pkg/tax_rate key, based on taxtype
|| $self->ut_enum('taxtype', [ qw( FS::cust_main_county FS::tax_rate ) ] )
- || $self->ut_foreign_key('pkgnum', 'cust_pkg', 'pkgnum' )
+ || $self->ut_number('pkgnum', 'cust_pkg', 'pkgnum' )
|| $self->ut_foreign_key('locationnum', 'cust_location', 'locationnum' )
|| $self->ut_money('amount')
|| $self->ut_foreign_key('taxable_billpkgnum', 'cust_bill_pkg', 'billpkgnum')
diff --git a/FS/FS/part_fee.pm b/FS/FS/part_fee.pm
index a10b066..954f70b 100644
--- a/FS/FS/part_fee.pm
+++ b/FS/FS/part_fee.pm
@@ -2,7 +2,6 @@ package FS::part_fee;
use strict;
use base qw( FS::o2m_Common FS::Record );
-use vars qw( $DEBUG );
use FS::Record qw( qsearch qsearchs );
use FS::pkg_class;
use FS::cust_bill_pkg_display;
@@ -10,7 +9,8 @@ use FS::part_pkg_taxproduct;
use FS::agent;
use FS::part_fee_usage;
-$DEBUG = 0;
+our $DEBUG = 0;
+our $default_class;
=head1 NAME
@@ -54,6 +54,9 @@ the invoice
=item disabled - 'Y' if the fee is disabled
=item classnum - the L<FS::pkg_class> that the fee belongs to, for reporting
+and placement on multisection invoices. Unlike packages, fees I<must> be
+assigned to a class; they will default to class named "Fees", which belongs
+to the same invoice section that normally contains taxes.
=item taxable - 'Y' if this fee should be considered a taxable sale.
Currently, taxable fees will be treated like they exist at the customer's
@@ -134,6 +137,13 @@ sub check {
$self->set('amount', 0) unless $self->amount;
$self->set('percent', 0) unless $self->percent;
+ $default_class ||= qsearchs('pkg_class', { classname => 'Fees' })
+ or die "default package fee class not found; run freeside-upgrade to continue.\n";
+
+ if (!$self->get('classnum')) {
+ $self->set('classnum', $default_class->classnum);
+ }
+
my $error =
$self->ut_numbern('feepart')
|| $self->ut_textn('comment')
diff --git a/FS/FS/pkg_category.pm b/FS/FS/pkg_category.pm
index adfadd7..c2361cc 100644
--- a/FS/FS/pkg_category.pm
+++ b/FS/FS/pkg_category.pm
@@ -3,7 +3,7 @@ use base qw( FS::category_Common );
use strict;
use vars qw( @ISA $me $DEBUG );
-use FS::Record qw( qsearch );
+use FS::Record qw( qsearch qsearchs );
use FS::pkg_class;
use FS::part_pkg;
@@ -145,6 +145,40 @@ sub _upgrade_data {
$weight += 10;
}
}
+
+ # create default category for package fees
+ my $tax_category_name = 'Taxes, Surcharges, and Fees';
+ my $tax_category = qsearchs('pkg_category',
+ { categoryname => $tax_category_name }
+ );
+ if (!$tax_category) {
+ $tax_category = FS::pkg_category->new({
+ categoryname => $tax_category_name,
+ weight => 1000, # doesn't really matter
+ });
+ my $error = $tax_category->insert;
+ die "error creating tax category: $error\n" if $error;
+ }
+
+ my $fee_class_name = 'Fees'; # does not appear on invoice
+ my $fee_class = qsearchs('pkg_class', { classname => $fee_class_name });
+ if (!$fee_class) {
+ $fee_class = FS::pkg_class->new({
+ classname => $fee_class_name,
+ categorynum => $tax_category->categorynum,
+ });
+ my $error = $fee_class->insert;
+ die "error creating fee class: $error\n" if $error;
+ }
+
+ # assign it to all fee defs that don't otherwise have a class
+ foreach my $part_fee (qsearch('part_fee', { classnum => '' })) {
+ $part_fee->set('classnum', $fee_class->classnum);
+ my $error = $part_fee->replace;
+ die "error assigning default class to fee def#".$part_fee->feepart .
+ ":$error\n" if $error;
+ }
+
'';
}
diff --git a/conf/invoice_html b/conf/invoice_html
index e9b0bdf..06ee775 100644
--- a/conf/invoice_html
+++ b/conf/invoice_html
@@ -166,15 +166,12 @@
&{$section->{description_generator}}($line);
} else {
my $class = 'invoice_desc_more';
- if ( $line->{'ref'} and $line->{'ref'} ne $lastref ) {
+ if ( ($line->{'ref'} || 0) ne $lastref ) {
# then it's a new package (not a continuation)
$class = 'invoice_desc';
}
$OUT .= '<tr class="'.$class.'">
<td align="center">';
- #if ( $line->{'ref'} ne $lastref ) {
- # $OUT .= $line->{'ref'};
- #}
$OUT .= '</td>
<td align="left">'. $line->{'description'}. '</td>';
if ( $unitprices ) {
@@ -185,7 +182,7 @@
$OUT .= '<td align="right">'. $line->{'amount'}. '</td>';
}
$OUT .= '</tr>';
- $lastref = $line->{'ref'};
+ $lastref = $line->{'ref'} || 0;
if ( @{$line->{'ext_description'} } ) {
unless ( $section->{description_generator} ) {
$OUT .= '<tr class="invoice_extdesc"><td></td><td';
diff --git a/conf/invoice_latex b/conf/invoice_latex
index 822afcb..40ec703 100644
--- a/conf/invoice_latex
+++ b/conf/invoice_latex
@@ -327,12 +327,12 @@
# Don't break-up small packages.
my $rowbreak = @$ext_description < 5 ? '*' : '';
- $OUT .= "\\hline\n" if ($line->{'ref'} && $line->{'ref'} ne $lastref);
+ $OUT .= "\\hline\n" if (($line->{'ref'} || 0) ne $lastref);
if ($section->{description_generator}) {
$OUT .= &{$section->{description_generator}}($line);
} else {
$OUT .= '\FSdesc'.
- '{}'. #'{' . ( $line->{'ref'} ne $lastref ? $line->{'ref'} : '' ) . '}'.
+ '{}'.
'{' . $line->{'description'} . '}' ;
if ( $unitprices and length($line->{'unit_amount'}) ) {
# then show the unit amount and quantity
@@ -345,7 +345,7 @@
}
$OUT .= '{\\dollar' . $line->{'amount'} . "}${rowbreak}\n";
}
- $lastref = $line->{'ref'};
+ $lastref = $line->{'ref'} || 0;
foreach my $ext_desc (@$ext_description) {
if ($section->{extended_description_generator}) {
-----------------------------------------------------------------------
Summary of changes:
FS/FS/Template_Mixin.pm | 106 +++++++++++++++++++++--------------
FS/FS/cust_bill_pkg_tax_location.pm | 2 +-
FS/FS/part_fee.pm | 14 ++++-
FS/FS/pkg_category.pm | 36 +++++++++++-
conf/invoice_html | 7 +--
conf/invoice_latex | 6 +-
6 files changed, 118 insertions(+), 53 deletions(-)
More information about the freeside-commits
mailing list