From 808b89d9c1f34c9c66064da212ab7036b85973a1 Mon Sep 17 00:00:00 2001 From: jeff Date: Fri, 12 Sep 2008 02:28:46 +0000 Subject: [PATCH] re-repurpose cust_bill_pkg --- FS/FS/Schema.pm | 25 +---- FS/FS/cust_bill.pm | 243 ++++++++++++++++++++++------------------- FS/FS/cust_bill_pkg.pm | 173 +++++++++++++++++++++++------ FS/FS/cust_bill_pkg_display.pm | 158 +++++++++++++++++++++++++++ FS/FS/cust_main.pm | 116 ++++++-------------- FS/MANIFEST | 2 + FS/t/cust_bill_pkg_display.t | 5 + 7 files changed, 472 insertions(+), 250 deletions(-) create mode 100644 FS/FS/cust_bill_pkg_display.pm create mode 100644 FS/t/cust_bill_pkg_display.t diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index d354561e5..c0fd4666a 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -519,42 +519,25 @@ sub tables_hashref { ], 'primary_key' => 'detailnum', 'unique' => [], - 'index' => [ [ 'billpkgnum' ], [ 'pkgnum', 'invnum' ] ], + 'index' => [ [ 'billpkgnum' ], [ 'classnum' ], [ 'pkgnum', 'invnum' ] ], }, - #instead of 'duplicate', 'char', 'NULL', 1, '', '', - # that way we keep display vs *TOTALLY* out of the table for actual - # finanancial line items 'cust_bill_pkg_display' => { 'columns' => [ 'billpkgdisplaynum', 'serial', '', '', '', '', 'billpkgnum', 'int', '', '', '', '', 'section', 'varchar', 'NULL', $char_d, '', '', - #override the linked real one?#'unitsetup', @money_typen, '', '', - #this too?#'unitrecur', @money_typen, '', '', + #'unitsetup', @money_typen, '', '', #override the linked real one? + #'unitrecur', @money_typen, '', '', #this too? 'post_total', 'char', 'NULL', 1, '', '', 'type', 'char', 'NULL', 1, '', '', - #any other fields we need to control this display-only line item... + 'summary', 'char', 'NULL', 1, '', '', ], 'primary_key' => 'billpkgdisplaynum', 'unique' => [], 'index' => [ ['billpkgnum'], ], }, - #and this, to break down a line item into slices for taxation purposes - #(instead of creating usage line items for each usage class) - 'cust_bill_pkg_slice' => { - 'columns' => [ - 'slicenum', 'serial', '', '', '', '', - 'billpkgnum', 'int', '', '', '', '', - 'amount', @money_typen, '', '', - 'classnum', 'int', '', '', '', '', - ], - 'primary_key' => 'slicenum', - 'unique' => [], - 'index' => [ [ 'billpkgnum' ], [ 'classnum' ], ], - }, - 'cust_credit' => { 'columns' => [ 'crednum', 'serial', '', '', '', '', diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 61ae6c092..83a79658a 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -17,6 +17,7 @@ use FS::Record qw( qsearch qsearchs dbh ); use FS::cust_main_Mixin; use FS::cust_main; use FS::cust_bill_pkg; +use FS::cust_bill_pkg_display; use FS::cust_credit; use FS::cust_pay; use FS::cust_pkg; @@ -2598,31 +2599,54 @@ sub _items_sections { { if ( $cust_bill_pkg->pkgnum > 0 ) { + my $usage = $cust_bill_pkg->usage; + + foreach my $display ($cust_bill_pkg->cust_bill_pkg_display) { + my $desc = $display->section; + my $type = $display->type; + + if ( $display->post_total ) { + if (! $type || $type eq 'S') { + $l{$desc} += $cust_bill_pkg->setup + if ( $cust_bill_pkg->setup != 0 ); + } + + if (! $type) { + $l{$desc} += $cust_bill_pkg->recur + if ( $cust_bill_pkg->recur != 0 ); + } + + if ($type && $type eq 'R') { + $l{$desc} += $cust_bill_pkg->recur - $usage + if ( $cust_bill_pkg->recur != 0 ); + } + + if ($type && $type eq 'U') { + $l{$desc} += $usage; + } + + } else { + if (! $type || $type eq 'S') { + $s{$desc} += $cust_bill_pkg->setup + if ( $cust_bill_pkg->setup != 0 ); + } + + if (! $type) { + $s{$desc} += $cust_bill_pkg->recur + if ( $cust_bill_pkg->recur != 0 ); + } + + if ($type && $type eq 'R') { + $s{$desc} += $cust_bill_pkg->recur - $usage + if ( $cust_bill_pkg->recur != 0 ); + } + + if ($type && $type eq 'U') { + $s{$desc} += $usage; + } - my $desc = $cust_bill_pkg->section; - my $dup_desc = $cust_bill_pkg->duplicate_section; - - if ($cust_bill_pkg->duplicate) { - $s{$dup_desc} += $cust_bill_pkg->setup - if ( $cust_bill_pkg->setup != 0 ); - - $s{$dup_desc} += $cust_bill_pkg->recur - if ( $cust_bill_pkg->recur != 0 ); - } - - if ( $cust_bill_pkg->post_total ) { - $l{$desc} += $cust_bill_pkg->setup - if ( $cust_bill_pkg->setup != 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 ); } } @@ -2690,13 +2714,7 @@ sub _items_pkg { my %options = @_; my $section = $options{'section'}; my $desc = $section->{'description'}; - my @cust_bill_pkg = - grep { $_->pkgnum && - ( defined($section) - ? ( $_->section eq $desc || $_->duplicate_section eq $desc ) - : 1 - ) - } $self->cust_bill_pkg; + my @cust_bill_pkg = grep { $_->pkgnum } $self->cust_bill_pkg; $self->_items_cust_bill_pkg(\@cust_bill_pkg, %options); } @@ -2724,86 +2742,94 @@ sub _items_cust_bill_pkg { my $escape_function = $opt{escape_function} || sub { shift }; my $format_function = $opt{format_function} || ''; my $unsquelched = $opt{unsquelched} || ''; + my $section = $opt{section}->{description} if $opt{section}; my @b = (); - my $last_pkgnum = ''; foreach my $cust_bill_pkg ( @$cust_bill_pkg ) { + foreach my $display ( grep { defined($section) + ? $_->section eq $section + : 1 + } + $cust_bill_pkg->cust_bill_pkg_display + ) + { - my $cust_pkg = $cust_bill_pkg->cust_pkg; - - my $desc = $cust_bill_pkg->desc; - - my %details_opt = ( 'format' => $format, - 'escape_function' => $escape_function, - 'format_function' => $format_function, - ); - - if ( $cust_bill_pkg->pkgnum > 0 ) { + my $type = $display->type; - if ( $cust_bill_pkg->setup != 0 ) { + my $cust_pkg = $cust_bill_pkg->cust_pkg; - my $description = $desc; - $description .= ' Setup' if $cust_bill_pkg->recur != 0; + my $desc = $cust_bill_pkg->desc; - my @d = map &{$escape_function}($_), - $cust_pkg->h_labels_short($self->_date); - push @d, $cust_bill_pkg->details(%details_opt) - if $cust_bill_pkg->recur == 0; + my %details_opt = ( 'format' => $format, + 'escape_function' => $escape_function, + 'format_function' => $format_function, + ); - push @b, { - description => $description, - #pkgpart => $part_pkg->pkgpart, - pkgnum => $cust_bill_pkg->pkgnum, - amount => sprintf("%.2f", $cust_bill_pkg->setup), - unit_amount => sprintf("%.2f", $cust_bill_pkg->unitsetup), - quantity => $cust_bill_pkg->quantity, - ext_description => \@d, - }; + if ( $cust_bill_pkg->pkgnum > 0 ) { - $last_pkgnum = ''; + if ( $cust_bill_pkg->setup != 0 && (!$type || $type eq 'S') ) { - } + my $description = $desc; + $description .= ' Setup' if $cust_bill_pkg->recur != 0; - if ( $cust_bill_pkg->recur != 0 ) { + my @d = map &{$escape_function}($_), + $cust_pkg->h_labels_short($self->_date); + push @d, $cust_bill_pkg->details(%details_opt) + if $cust_bill_pkg->recur == 0; - my $is_summary = - ( $cust_bill_pkg->duplicate && - $opt{section}->{description} ne $cust_bill_pkg->section - ); - my $description = $is_summary ? "Usage charges" : $desc; + push @b, { + description => $description, + #pkgpart => $part_pkg->pkgpart, + pkgnum => $cust_bill_pkg->pkgnum, + amount => sprintf("%.2f", $cust_bill_pkg->setup), + unit_amount => sprintf("%.2f", $cust_bill_pkg->unitsetup), + quantity => $cust_bill_pkg->quantity, + ext_description => \@d, + }; - unless ( $conf->exists('disable_line_item_date_ranges') ) { - $description .= " (" . time2str("%x", $cust_bill_pkg->sdate). - " - ". time2str("%x", $cust_bill_pkg->edate). ")"; } - #at least until cust_bill_pkg has "past" ranges in addition to - #the "future" sdate/edate ones... see #3032 - my @d = (); - push @d, map &{$escape_function}($_), - $cust_pkg->h_labels_short($self->_date) - #$cust_bill_pkg->edate, - #$cust_bill_pkg->sdate), - unless ($cust_bill_pkg->pkgnum eq $last_pkgnum); - - @d = () if ($cust_bill_pkg->itemdesc || $is_summary); - push @d, $cust_bill_pkg->details(%details_opt) - unless $is_summary; - - if ($cust_bill_pkg->pkgnum eq $last_pkgnum) { - - $b[$#b]->{amount} = - sprintf("%.2f", $b[$#b]->{amount} + $cust_bill_pkg->recur); - push @{$b[$#b]->{ext_description}}, @d; - - }else{ - + if ( $cust_bill_pkg->recur != 0 && + ( !$type || $type eq 'R' || $type eq 'U' ) + ) + { + + my $is_summary = $display->summary; + my $description = $is_summary ? "Usage charges" : $desc; + + unless ( $conf->exists('disable_line_item_date_ranges') ) { + $description .= " (" . time2str("%x", $cust_bill_pkg->sdate). + " - ". time2str("%x", $cust_bill_pkg->edate). ")"; + } + + #at least until cust_bill_pkg has "past" ranges in addition to + #the "future" sdate/edate ones... see #3032 + my @d = (); + push @d, map &{$escape_function}($_), + $cust_pkg->h_labels_short($self->_date) + #$cust_bill_pkg->edate, + #$cust_bill_pkg->sdate), + ; + + @d = () if ($cust_bill_pkg->itemdesc || $is_summary); + push @d, $cust_bill_pkg->details(%details_opt) + unless ($is_summary || $type && $type eq 'R'); + + my $amount = 0; + if (!$type) { + $amount = $cust_bill_pkg->recur; + }elsif($type eq 'R') { + $amount = $cust_bill_pkg->recur - $cust_bill_pkg->usage; + }elsif($type eq 'U') { + $amount = $cust_bill_pkg->usage; + } + push @b, { description => $description, #pkgpart => $part_pkg->pkgpart, pkgnum => $cust_bill_pkg->pkgnum, - amount => sprintf("%.2f", $cust_bill_pkg->recur), + amount => sprintf("%.2f", $amount), unit_amount => sprintf("%.2f", $cust_bill_pkg->unitrecur), quantity => $cust_bill_pkg->quantity, ext_description => \@d, @@ -2811,31 +2837,24 @@ sub _items_cust_bill_pkg { } - if ($conf->exists('separate_usage') && $cust_bill_pkg->type ne 'U') { - $last_pkgnum = ''; - }else{ - $last_pkgnum = $cust_bill_pkg->pkgnum; - } - } + } else { #pkgnum tax or one-shot line item (??) - } else { #pkgnum tax or one-shot line item (??) + if ( $cust_bill_pkg->setup != 0 ) { + push @b, { + 'description' => $desc, + 'amount' => sprintf("%.2f", $cust_bill_pkg->setup), + }; + } + if ( $cust_bill_pkg->recur != 0 ) { + push @b, { + 'description' => "$desc (". + time2str("%x", $cust_bill_pkg->sdate). ' - '. + time2str("%x", $cust_bill_pkg->edate). ')', + 'amount' => sprintf("%.2f", $cust_bill_pkg->recur), + }; + } - if ( $cust_bill_pkg->setup != 0 ) { - push @b, { - 'description' => $desc, - 'amount' => sprintf("%.2f", $cust_bill_pkg->setup), - }; } - if ( $cust_bill_pkg->recur != 0 ) { - push @b, { - 'description' => "$desc (". - time2str("%x", $cust_bill_pkg->sdate). ' - '. - time2str("%x", $cust_bill_pkg->edate). ')', - 'amount' => sprintf("%.2f", $cust_bill_pkg->recur), - }; - } - - $last_pkgnum = ''; } diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm index 2bfde6d28..ddda50452 100644 --- a/FS/FS/cust_bill_pkg.pm +++ b/FS/FS/cust_bill_pkg.pm @@ -1,18 +1,21 @@ package FS::cust_bill_pkg; use strict; -use vars qw( @ISA ); +use vars qw( @ISA $DEBUG ); use FS::Record qw( qsearch qsearchs dbdef dbh ); use FS::cust_main_Mixin; use FS::cust_pkg; use FS::part_pkg; use FS::cust_bill; use FS::cust_bill_pkg_detail; +use FS::cust_bill_pkg_display; use FS::cust_bill_pay_pkg; use FS::cust_credit_bill_pkg; @ISA = qw( FS::cust_main_Mixin FS::Record ); +$DEBUG = 0; + =head1 NAME FS::cust_bill_pkg - Object methods for cust_bill_pkg records @@ -57,24 +60,6 @@ supported: =item itemdesc - Line item description (overrides normal package description) -=item section - Invoice section (overrides normal package section) - -=cut - -sub section { - my ( $self, $value ) = @_; - if ( defined($value) ) { - $self->setfield('section', $value); - } else { - $self->getfield('section') || $self->part_pkg->categoryname; - } -} - -sub duplicate_section { - my $self = shift; - $self->duplicate ? $self->part_pkg->categoryname : ''; -} - =item quantity - If not set, defaults to 1 =item unitsetup - If not set, defaults to setup @@ -127,23 +112,31 @@ sub insert { return $error; } - unless ( defined dbdef->table('cust_bill_pkg_detail') && $self->get('details') ) { - $dbh->commit or die $dbh->errstr if $oldAutoCommit; - return ''; + if ( defined dbdef->table('cust_bill_pkg_detail') && $self->get('details') ) { + foreach my $detail ( @{$self->get('details')} ) { + my $cust_bill_pkg_detail = new FS::cust_bill_pkg_detail { + 'billpkgnum' => $self->billpkgnum, + 'format' => (ref($detail) ? $detail->[0] : '' ), + 'detail' => (ref($detail) ? $detail->[1] : $detail ), + 'amount' => (ref($detail) ? $detail->[2] : '' ), + 'classnum' => (ref($detail) ? $detail->[3] : '' ), + }; + $error = $cust_bill_pkg_detail->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } } - foreach my $detail ( @{$self->get('details')} ) { - my $cust_bill_pkg_detail = new FS::cust_bill_pkg_detail { - 'billpkgnum' => $self->billpkgnum, - 'format' => (ref($detail) ? $detail->[0] : '' ), - 'detail' => (ref($detail) ? $detail->[1] : $detail ), - 'amount' => (ref($detail) ? $detail->[2] : '' ), - 'classnum' => (ref($detail) ? $detail->[3] : '' ), - }; - $error = $cust_bill_pkg_detail->insert; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; + if ( defined dbdef->table('cust_bill_pkg_display') && $self->get('display') ){ + foreach my $cust_bill_pkg_display ( @{ $self->get('display') } ) { + $cust_bill_pkg_display->billpkgnum($self->billpkgnum); + $error = $cust_bill_pkg_display->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } } } @@ -194,7 +187,6 @@ sub check { || $self->ut_numbern('sdate') || $self->ut_numbern('edate') || $self->ut_textn('itemdesc') - || $self->ut_textn('section') ; return $error if $error; @@ -446,6 +438,79 @@ sub unitrecur { : $self->getfield('unitrecur'); } +=item disintegrate + +Returns a list of cust_bill_pkg objects each with no more than a single class +(including setup or recur) of charge. + +=cut + +sub disintegrate { + my $self = shift; + # XXX this goes away with cust_bill_pkg refactor + + my $cust_bill_pkg = new FS::cust_bill_pkg { $self->hash }; + my %cust_bill_pkg = (); + + $cust_bill_pkg{setup} = $cust_bill_pkg if $cust_bill_pkg->setup; + $cust_bill_pkg{recur} = $cust_bill_pkg if $cust_bill_pkg->recur; + + + #split setup and recur + if ($cust_bill_pkg->setup && $cust_bill_pkg->recur) { + my $cust_bill_pkg_recur = new FS::cust_bill_pkg { $cust_bill_pkg->hash }; + $cust_bill_pkg->set('details', []); + $cust_bill_pkg->recur(0); + $cust_bill_pkg->unitrecur(0); + $cust_bill_pkg->type(''); + $cust_bill_pkg_recur->setup(0); + $cust_bill_pkg_recur->unitsetup(0); + $cust_bill_pkg{recur} = $cust_bill_pkg_recur; + + } + + #split usage from recur + my $usage = sprintf( "%.2f", $cust_bill_pkg{recur}->usage ); + warn "usage is $usage\n" if $DEBUG; + if ($usage) { + my $cust_bill_pkg_usage = + new FS::cust_bill_pkg { $cust_bill_pkg{recur}->hash }; + $cust_bill_pkg_usage->recur( $usage ); + $cust_bill_pkg_usage->type( 'U' ); + my $recur = sprintf( "%.2f", $cust_bill_pkg{recur}->recur - $usage ); + $cust_bill_pkg{recur}->recur( $recur ); + $cust_bill_pkg{recur}->type( '' ); + $cust_bill_pkg{recur}->set('details', []); + $cust_bill_pkg{''} = $cust_bill_pkg_usage; + } + + #subdivide usage by usage_class + if (exists($cust_bill_pkg{''})) { + foreach my $class (grep { $_ } $self->usage_classes) { + my $usage = sprintf( "%.2f", $cust_bill_pkg{''}->usage($class) ); + my $cust_bill_pkg_usage = + new FS::cust_bill_pkg { $cust_bill_pkg{''}->hash }; + $cust_bill_pkg_usage->recur( $usage ); + $cust_bill_pkg_usage->set('details', []); + my $classless = sprintf( "%.2f", $cust_bill_pkg{''}->recur - $usage ); + $cust_bill_pkg{''}->recur( $classless ); + $cust_bill_pkg{$class} = $cust_bill_pkg_usage; + } + delete $cust_bill_pkg{''} unless $cust_bill_pkg{''}->recur; + } + +# # sort setup,recur,'', and the rest numeric && return +# my @result = map { $cust_bill_pkg{$_} } +# sort { my $ad = ($a=~/^\d+$/); my $bd = ($b=~/^\d+$/); +# ( $ad cmp $bd ) || ( $ad ? $a<=>$b : $b cmp $a ) +# } +# keys %cust_bill_pkg; +# +# return (@result); + + %cust_bill_pkg; +} + =item usage CLASSNUM Returns the amount of the charge associated with usage class CLASSNUM if @@ -510,6 +575,44 @@ sub usage_classes { } +=item cust_bill_pkg_display [ type => TYPE ] + +Returns an array of display information for the invoice line item optionally +limited to 'TYPE'. + +=cut + +sub cust_bill_pkg_display { + my ( $self, %opt ) = @_; + + my $default = + new FS::cust_bill_pkg_display { billpkgnum =>$self->billpkgnum }; + + return ( $default ) unless defined dbdef->table('cust_bill_pkg_display');#hmmm + + my $type = $opt{type} if exists $opt{type}; + my @result; + + if ( scalar( $self->get('display') ) ) { + @result = grep { defined($type) ? ($type eq $_->type) : 1 } + @{ $self->get('display') }; + }else{ + my $hashref = { 'billpkgnum' => $self->billpkgnum }; + $hashref->{type} = $type if defined($type); + + @result = qsearch ({ 'table' => 'cust_bill_pkg_display', + 'hashref' => { 'billpkgnum' => $self->billpkgnum }, + 'order_by' => 'ORDER BY billpkgdisplaynum', + }); + } + + push @result, $default unless ( scalar(@result) || $type ); + + @result; + +} + + =back =head1 BUGS diff --git a/FS/FS/cust_bill_pkg_display.pm b/FS/FS/cust_bill_pkg_display.pm new file mode 100644 index 000000000..93c6e87d6 --- /dev/null +++ b/FS/FS/cust_bill_pkg_display.pm @@ -0,0 +1,158 @@ +package FS::cust_bill_pkg_display; + +use strict; +use vars qw( @ISA ); +use FS::Record qw( qsearch qsearchs ); + +@ISA = qw(FS::Record); + +=head1 NAME + +FS::cust_bill_pkg_display - Object methods for cust_bill_pkg_display records + +=head1 SYNOPSIS + + use FS::cust_bill_pkg_display; + + $record = new FS::cust_bill_pkg_display \%hash; + $record = new FS::cust_bill_pkg_display { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::cust_bill_pkg_display object represents line item display information. +FS::cust_bill_pkg_display inherits from FS::Record. The following fields are +currently supported: + +=over 4 + +=item billpkgdisplaynum + +primary key + +=item billpkgnum + +billpkgnum + +=item section + +section + +=cut + +sub section { + my ( $self, $value ) = @_; + if ( defined($value) ) { + $self->setfield('section', $value); + } else { + $self->getfield('section') || $self->cust_bill_pkg->part_pkg->categoryname; + } +} + +=item post_total + +post_total + +=item type + +type + +=item summary + +summary + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new line item display object. To add the record to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I method. + +=cut + +sub table { 'cust_bill_pkg_display'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +=item delete + +Delete this record from the database. + +=cut + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=cut + +=item check + +Checks all fields to make sure this is a valid line item display object. +If there is an error, returns the error, otherwise returns false. Called by +the insert and replace methods. + +=cut + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('billpkgdisplaynum') + || $self->ut_number('billpkgnum') + || $self->ut_foreign_key('billpkgnum', 'cust_bill_pkg', 'billpkgnum') + || $self->ut_textn('section') + || $self->ut_enum('post_total', [ '', 'Y' ]) + || $self->ut_enum('type', [ '', 'S', 'R', 'U' ]) + || $self->ut_enum('summary', [ '', 'Y' ]) + ; + return $error if $error; + + $self->SUPER::check; +} + +=item cust_bill_pkg + +Returns the associated cust_bill_pkg (see L) for this +line item display object. + +=cut + +sub cust_bill_pkg { + my $self = shift; + qsearchs( 'cust_bill_pkg', { 'billpkgnum' => $self->billpkgnum } ) ; +} + +=back + +=head1 BUGS + + + +=head1 SEE ALSO + +L, L, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index e64d666bc..88d8bdd91 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -29,6 +29,7 @@ use FS::cust_pkg; use FS::cust_svc; use FS::cust_bill; use FS::cust_bill_pkg; +use FS::cust_bill_pkg_display; use FS::cust_pay; use FS::cust_pay_pending; use FS::cust_pay_void; @@ -2567,89 +2568,40 @@ sub _handle_taxes { } #if $conf->exists('enable_taxproducts') ... - my $section = $cust_pkg->part_pkg->option('usage_section', 'Hush!') - if $cust_pkg->part_pkg->option('separate_usage', 'Hush!' ); - my $want_duplicate = - $cust_pkg->part_pkg->option('summarize_usage', 'Hush!') && - $cust_pkg->part_pkg->option('usage_section', 'Hush!'); + my @display = (); + if ( $conf->exists('separate_usage') ) { + my $section = $cust_pkg->part_pkg->option('usage_section', 'Hush!'); + my $summary = $cust_pkg->part_pkg->option('summarize_usage', 'Hush!'); + push @display, new FS::cust_bill_pkg_display { type => 'S' }; + push @display, new FS::cust_bill_pkg_display { type => 'R' }; + push @display, new FS::cust_bill_pkg_display { type => 'U', + section => $section + }; + if ($section && $summary) { + $display[2]->post_total('Y'); + push @display, new FS::cust_bill_pkg_display { type => 'U', + summary => 'Y', + } + } + } + $cust_bill_pkg->set('display', \@display); -#BUNK. DO NOT CREATE DUPLICATE cust_bill_pkg!!!!!!!!!!!! -# -# # XXX this mostly goes away with cust_bill_pkg refactor -# -# $cust_bill_pkg{setup} = $cust_bill_pkg if $cust_bill_pkg->setup; -# $cust_bill_pkg{recur} = $cust_bill_pkg if $cust_bill_pkg->recur; -# -# -# #split setup and recur -# if ($cust_bill_pkg->setup && $cust_bill_pkg->recur) { -# my $cust_bill_pkg_recur = new FS::cust_bill_pkg { $cust_bill_pkg->hash }; -# $cust_bill_pkg_recur->details($cust_bill_pkg-> -# $cust_bill_pkg_recur->setup(0); -# $cust_bill_pkg_recur->unitsetup(0); -# $cust_bill_pkg{recur} = $cust_bill_pkg_recur; -# -# $cust_bill_pkg->set('details', []); -# $cust_bill_pkg->recur(0); -# $cust_bill_pkg->unitrecur(0); -# $cust_bill_pkg->type(''); -# } -# -# #split usage from recur -# my $usage = sprintf( "%.2f", $cust_bill_pkg{recur}->usage ); -# warn "usage is $usage\n" if $DEBUG; -# if ($usage) { -# my $cust_bill_pkg_usage = -# new FS::cust_bill_pkg { $cust_bill_pkg{recur}->hash }; -# $cust_bill_pkg_usage->recur( $usage ); -# $cust_bill_pkg_usage->type( 'U' ); -# $cust_bill_pkg_usage->duplicate( $want_duplicate ? 'Y' : '' ); -# $cust_bill_pkg_usage->section( $section ); -# $cust_bill_pkg_usage->post_total( $want_duplicate ? 'Y' : '' ); -# my $recur = sprintf( "%.2f", $cust_bill_pkg{recur}->recur - $usage ); -# $cust_bill_pkg{recur}->recur( $recur ); -# $cust_bill_pkg{recur}->type( '' ); -# $cust_bill_pkg{recur}->set('details', []); -# $cust_bill_pkg{''} = $cust_bill_pkg_usage; -# } -# -# #subdivide usage by usage_class -# if (exists($cust_bill_pkg{''})) { -# foreach my $class (grep {$_ && $_ ne 'setup' && $_ ne 'recur' } @classes) { -# my $usage = sprintf( "%.2f", $cust_bill_pkg{''}->usage($class) ); -# my $cust_bill_pkg_usage = -# new FS::cust_bill_pkg { $cust_bill_pkg{''}->hash }; -# $cust_bill_pkg_usage->recur( $usage ); -# $cust_bill_pkg_usage->set('details', []); -# my $classless = sprintf( "%.2f", $cust_bill_pkg{''}->recur - $usage ); -# $cust_bill_pkg{''}->recur( $classless ); -# $cust_bill_pkg{$class} = $cust_bill_pkg_usage; -# } -# delete $cust_bill_pkg{''} unless $cust_bill_pkg{''}->recur; -# } -# -# foreach my $key (keys %cust_bill_pkg) { -# my @taxes = @{ $taxes{$key} }; -# my $cust_bill_pkg = $cust_bill_pkg{$key}; -# -# foreach my $tax ( @taxes ) { -# my $taxname = ref( $tax ). ' '. $tax->taxnum; -# if ( exists( $taxlisthash->{ $taxname } ) ) { -# push @{ $taxlisthash->{ $taxname } }, $cust_bill_pkg; -# }else{ -# $taxlisthash->{ $taxname } = [ $tax, $cust_bill_pkg ]; -# } -# } -# } -# -# # sort setup,recur,'', and the rest numeric && return -# my @result = map { $cust_bill_pkg{$_} } -# sort { my $ad = ($a=~/^\d+$/); my $bd = ($b=~/^\d+$/); -# ( $ad cmp $bd ) || ( $ad ? $a<=>$b : $b cmp $a ) -# } -# keys %cust_bill_pkg; -# -# \@result; + my %tax_cust_bill_pkg = $cust_bill_pkg->disintegrate; + foreach my $key (keys %tax_cust_bill_pkg) { + my @taxes = @{ $taxes{$key} }; + my $tax_cust_bill_pkg = $tax_cust_bill_pkg{$key}; + + foreach my $tax ( @taxes ) { + my $taxname = ref( $tax ). ' '. $tax->taxnum; + if ( exists( $taxlisthash->{ $taxname } ) ) { + push @{ $taxlisthash->{ $taxname } }, $tax_cust_bill_pkg; + }else{ + $taxlisthash->{ $taxname } = [ $tax, $tax_cust_bill_pkg ]; + } + } + } + + ''; } sub _gather_taxes { diff --git a/FS/MANIFEST b/FS/MANIFEST index b1f201d0a..5bae060c1 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -422,5 +422,7 @@ FS/cust_svc_option.pm t/cust_svc_option.t FS/usage_class.pm t/usage_class.t +FS/cust_bill_pkg_display.pm +t/cust_bill_pkg_display.t FS/cust_pkg_detail.pm t/cust_pkg_detail.t diff --git a/FS/t/cust_bill_pkg_display.t b/FS/t/cust_bill_pkg_display.t new file mode 100644 index 000000000..d84dbdf05 --- /dev/null +++ b/FS/t/cust_bill_pkg_display.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::cust_bill_pkg_display; +$loaded=1; +print "ok 1\n"; -- 2.11.0