summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FS/FS/Schema.pm3
-rw-r--r--FS/FS/cust_bill.pm53
-rw-r--r--FS/FS/cust_bill_pkg.pm35
-rw-r--r--FS/FS/cust_main.pm18
-rw-r--r--FS/FS/part_pkg/voip_cdr.pm37
-rw-r--r--conf/invoice_latex1
6 files changed, 122 insertions, 25 deletions
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 6c899c5..33b3064 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -496,9 +496,12 @@ sub tables_hashref {
'sdate', @date_type, '', '',
'edate', @date_type, '', '',
'itemdesc', 'varchar', 'NULL', $char_d, '', '',
+ 'section', 'varchar', 'NULL', $char_d, '', '',
'quantity', 'int', 'NULL', '', '', '',
'unitsetup', @money_typen, '', '',
'unitrecur', @money_typen, '', '',
+ 'duplicate', 'char', 'NULL', 1, '', '', # does this need to be in db?
+ 'post_total', 'char', 'NULL', 1, '', '',
],
'primary_key' => 'billpkgnum',
'unique' => [],
diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm
index 96c1db7..3274d38 100644
--- a/FS/FS/cust_bill.pm
+++ b/FS/FS/cust_bill.pm
@@ -1999,9 +1999,11 @@ sub print_generic {
my $adjust_section = { 'description' => 'Credits, Payments, and Adjustments',
'subtotal' => 0 }; # adjusted below
+ my $unsquelched = $params{unsquelch_cdr} || $cust_main->squelch_cdr ne 'Y';
my $multisection = $conf->exists('invoice_sections', $cust_main->agentnum);
+ my $late_sections = [];
if ( $multisection ) {
- push @sections, $self->_items_sections;
+ push @sections, $self->_items_sections( $late_sections );
}else{
push @sections, { 'description' => '', 'subtotal' => '' };
}
@@ -2040,7 +2042,7 @@ sub print_generic {
push @buf, ['',''];
}
- foreach my $section (@sections) {
+ foreach my $section (@sections, @$late_sections) {
$section->{'subtotal'} = $other_money_char.
sprintf('%.2f', $section->{'subtotal'})
@@ -2056,8 +2058,8 @@ sub print_generic {
$options{'section'} = $section if $multisection;
$options{'format'} = $format;
$options{'escape_function'} = $escape_function;
- $options{'format_function'} = sub { () }
- unless $params{unsquelch_cdr} || $cust_main->squelch_cdr ne 'Y';
+ $options{'format_function'} = sub { () } unless $unsquelched;
+ $options{'unsquelched'} = $unsquelched;
foreach my $line_item ( $self->_items_pkg(%options) ) {
my $detail = {
@@ -2278,6 +2280,11 @@ sub print_generic {
}
}
+ if ( $multisection ) {
+ push @sections, @$late_sections
+ if $unsquelched;
+ }
+
$invoice_lines = 0;
my $wasfunc = 0;
foreach ( grep /invoice_lines\(\d*\)/, @invoice_template ) { #kludgy
@@ -2537,24 +2544,42 @@ sub invnum_date_pretty {
sub _items_sections {
my $self = shift;
+ my $late = shift;
my %s = ();
- foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) {
+ my %l = ();
+
+ foreach my $cust_bill_pkg ( $self->cust_bill_pkg )
+ {
if ( $cust_bill_pkg->pkgnum > 0 ) {
- my $desc = $cust_bill_pkg->part_pkg->categoryname;
+ my $desc = $cust_bill_pkg->section;
- $s{$desc} += $cust_bill_pkg->setup
- if ( $cust_bill_pkg->setup != 0 );
+ if ( $cust_bill_pkg->post_total ) {
+ $l{$desc} += $cust_bill_pkg->setup
+ if ( $cust_bill_pkg->setup != 0 );
- $s{$desc} += $cust_bill_pkg->recur
- if ( $cust_bill_pkg->recur != 0 );
+ $l{$desc} += $cust_bill_pkg->recur
+ if ( $cust_bill_pkg->recur != 0 );
+
+ } else {
+ $s{$desc} += $cust_bill_pkg->setup
+ if ( $cust_bill_pkg->setup != 0 );
+
+ $s{$desc} += $cust_bill_pkg->recur
+ if ( $cust_bill_pkg->recur != 0 );
+ }
}
}
+ push @$late, map { { 'description' => $_,
+ 'subtotal' => $l{$_},
+ 'post_total' => 1,
+ } } sort keys %l;
+
map { {'description' => $_, 'subtotal' => $s{$_}} } sort keys %s;
}
@@ -2613,7 +2638,7 @@ sub _items_pkg {
my @cust_bill_pkg =
grep { $_->pkgnum &&
( defined($section)
- ? $_->part_pkg->categoryname eq $section->{'description'}
+ ? $_->section eq $section->{'description'}
: 1
)
} $self->cust_bill_pkg;
@@ -2643,9 +2668,13 @@ sub _items_cust_bill_pkg {
my $format = $opt{format} || '';
my $escape_function = $opt{escape_function} || sub { shift };
my $format_function = $opt{format_function} || '';
+ my $unsquelched = $opt{unsquelched} || '';
my @b = ();
- foreach my $cust_bill_pkg ( @$cust_bill_pkg ) {
+ foreach my $cust_bill_pkg ( grep { $unsquelched ? 1 : ! $_->separate_cdr }
+ @$cust_bill_pkg
+ )
+ {
my $cust_pkg = $cust_bill_pkg->cust_pkg;
diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm
index 638e707..b3b8ea5 100644
--- a/FS/FS/cust_bill_pkg.pm
+++ b/FS/FS/cust_bill_pkg.pm
@@ -57,6 +57,24 @@ supported:
=item itemdesc - Line item description (overrides normal package description)
+=item section - Invoice section (overrides normal package section)
+
+=duplicate - Indicates this item appears elsewhere on the invoice
+ (and should not be retaxed or reincluded in totals)
+
+=post_total - A hint that this item should appear after invoice totals
+
+=cut
+
+sub section {
+ my ( $self, $value ) = @_;
+ if ( defined($value) ) {
+ $self->setfield('section', $value);
+ } else {
+ $self->getfield('section') || $self->part_pkg->categoryname;
+ }
+}
+
=item quantity - If not set, defaults to 1
=item unitsetup - If not set, defaults to setup
@@ -174,6 +192,9 @@ sub check {
|| $self->ut_numbern('sdate')
|| $self->ut_numbern('edate')
|| $self->ut_textn('itemdesc')
+ || $self->ut_textn('section')
+ || $self->ut_enum('duplicate', [ '', 'Y' ])
+ || $self->ut_enum('post_total', [ '', 'Y' ])
;
return $error if $error;
@@ -382,7 +403,7 @@ line item.
sub units {
my $self = shift;
- $self->part_pkg->calc_units($self->cust_pkg);
+ $self->pkgnum ? $self->part_pkg->calc_units($self->cust_pkg) : 0; # 1?
}
=item quantity
@@ -425,6 +446,18 @@ sub unitrecur {
: $self->getfield('unitrecur');
}
+=item separate_cdr
+
+Returns true if this line item represents a cdr line item in its own section.
+
+=cut
+
+# lame, but works for now
+sub separate_cdr {
+ my( $self ) = shift;
+ $self->pkgnum && $self->section ne $self->part_pkg->categoryname;
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 8873a5b..51270d6 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -2491,18 +2491,20 @@ sub _make_lines {
unless $part_pkg->pkgpart == $real_pkgpart;
push @$appended_cust_bill_pkg, $cust_bill_pkg;
- $$total_setup += $cust_bill_pkg->setup;
- $$total_recur += $cust_bill_pkg->recur;
+ unless ($cust_bill_pkg->duplicate) {
+ $$total_setup += $cust_bill_pkg->setup;
+ $$total_recur += $cust_bill_pkg->recur;
- ###
- # handle taxes
- ###
+ ###
+ # handle taxes
+ ###
- unless ( $self->tax =~ /Y/i || $self->payby eq 'COMP' ) {
+ unless ( $self->tax =~ /Y/i || $self->payby eq 'COMP' ) {
- $self->_handle_taxes($part_pkg, $taxlisthash, $cust_bill_pkg);
+ $self->_handle_taxes($part_pkg, $taxlisthash, $cust_bill_pkg);
- } #unless $self->tax =~ /Y/i || $self->payby eq 'COMP'
+ } #unless $self->tax =~ /Y/i || $self->payby eq 'COMP'
+ }
}
}
diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm
index 14f812f..991c33c 100644
--- a/FS/FS/part_pkg/voip_cdr.pm
+++ b/FS/FS/part_pkg/voip_cdr.pm
@@ -89,6 +89,13 @@ tie my %rating_method, 'Tie::IxHash',
'type' => 'checkbox',
},
+ 'usage_section' => { 'name' => 'Section in which to place separate usage charges',
+ },
+
+ 'summarize_usage' => { 'name' => 'Include usage summary with recurring charges when usage is in separate section',
+ 'type' => 'checkbox',
+ },
+
#XXX also have option for an external db
# 'cdr_location' => { 'name' => 'CDR database location'
# 'type' => 'select',
@@ -120,7 +127,7 @@ tie my %rating_method, 'Tie::IxHash',
disable_src
domestic_prefix international_prefix
use_amaflags use_disposition output_format
- separate_usage
+ separate_usage summarize_usage usage_section
)
],
'weight' => 40,
@@ -473,7 +480,12 @@ sub append_cust_bill_pkgs {
return []
unless $charges; # unless @details?
- my $cust_bill_pkg = new FS::cust_bill_pkg {
+ my @cust_bill_pkg = ();
+
+ my $want_summary = $self->option('summarize_usage', 'Hush!') &&
+ $self->option('usage_section', 'Hush!');
+
+ push @cust_bill_pkg, new FS::cust_bill_pkg {
'pkgnum' => $cust_pkg->pkgnum,
'setup' => 0,
'unitsetup' => 0,
@@ -483,10 +495,27 @@ sub append_cust_bill_pkgs {
'sdate' => $$sdate,
'edate' => $cust_pkg->bill, # already fiddled
'itemdesc' => 'Usage charges', # configurable?
- 'details' => \@details,
+ 'duplicate' => 'Y',
+ }
+ if $want_summary;
+
+ push @cust_bill_pkg, new FS::cust_bill_pkg {
+ 'pkgnum' => $cust_pkg->pkgnum,
+ 'setup' => 0,
+ 'unitsetup ' => 0,
+ 'recur' => sprintf( "%.2f", $charges), # hmmm
+ 'unitrecur ' => 0,
+ 'quantity' => $cust_pkg->quantity,
+ 'sdate' => $$sdate,
+ 'edate' => $cust_pkg->bill, # already fiddled
+ 'itemdesc' => 'Usage charges', # configurable?
+ 'section' => $self->option('usage_section', 'Hush!'),
+ 'details' => \@details,
+ 'post_total' => ( $want_summary ? 'Y' : '' ),
};
- return [ $cust_bill_pkg ];
+
+ return [ @cust_bill_pkg ];
}
1;
diff --git a/conf/invoice_latex b/conf/invoice_latex
index ddd068e..fe910b2 100644
--- a/conf/invoice_latex
+++ b/conf/invoice_latex
@@ -235,6 +235,7 @@ Terms: [@-- $terms --@]\\
$OUT .= '\large\textsc{'. $section->{'pretotal'}. '}\\\\';
$OUT .= '\\end{flushright}';
}
+ $OUT .= '\pagebreak' if $section{'post_total'};
$OUT .= '\captionsetup{singlelinecheck=false,justification=raggedright,font={Large,sc,bf}}';
$OUT .= '\begin{longtable}{cllllllr}';
$OUT .= '\caption*{ ';