From 20d7ca3a3e37b9748eed3f7ef362f04c757420ba Mon Sep 17 00:00:00 2001 From: jeff Date: Fri, 8 Aug 2008 18:13:05 +0000 Subject: [PATCH] cdrs can be in separate invoice section, after total, summarized inline, with hints for page breaks --- FS/FS/Schema.pm | 3 +++ FS/FS/cust_bill.pm | 53 +++++++++++++++++++++++++++++++++++----------- FS/FS/cust_bill_pkg.pm | 35 +++++++++++++++++++++++++++++- FS/FS/cust_main.pm | 18 +++++++++------- FS/FS/part_pkg/voip_cdr.pm | 37 ++++++++++++++++++++++++++++---- conf/invoice_latex | 1 + 6 files changed, 122 insertions(+), 25 deletions(-) diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 6c899c5a1..33b306424 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 96c1db7fb..3274d3875 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 638e707c4..b3b8ea596 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 8873a5bf6..51270d6dd 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 14f812fc1..991c33cf6 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 ddd068ed6..fe910b24e 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*{ '; -- 2.11.0