From: ivan Date: Thu, 6 Feb 2003 05:26:50 +0000 (+0000) Subject: time/data detail on invoices X-Git-Tag: freeside_1_5_0pre1~47 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=c232fac0743999105f6948b9fa352fe2293b09f8 time/data detail on invoices --- diff --git a/FS/FS.pm b/FS/FS.pm index a2df6f175..e4a32082c 100644 --- a/FS/FS.pm +++ b/FS/FS.pm @@ -102,6 +102,8 @@ L - Invoice class L - Invoice line item class +L - Invoice line item detail class + L - Invoice event definition class L - Completed invoice event class diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index c661baa95..aa82eb6f8 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -953,38 +953,43 @@ sub print_text { } #new charges - foreach ( ( grep { $_->pkgnum } $self->cust_bill_pkg ), #packages first - ( grep { ! $_->pkgnum } $self->cust_bill_pkg ), #then taxes + foreach my $cust_bill_pkg ( + ( grep { $_->pkgnum } $self->cust_bill_pkg ), #packages first + ( grep { ! $_->pkgnum } $self->cust_bill_pkg ), #then taxes ) { - if ( $_->pkgnum ) { + if ( $cust_bill_pkg->pkgnum ) { - my($cust_pkg)=qsearchs('cust_pkg', { 'pkgnum', $_->pkgnum } ); - my($part_pkg)=qsearchs('part_pkg',{'pkgpart'=>$cust_pkg->pkgpart}); - my($pkg)=$part_pkg->pkg; + my $cust_pkg = qsearchs('cust_pkg', { pkgnum =>$cust_bill_pkg->pkgnum } ); + my $part_pkg = qsearchs('part_pkg', { pkgpart=>$cust_pkg->pkgpart } ); + my $pkg = $part_pkg->pkg; - if ( $_->setup != 0 ) { - push @buf, [ "$pkg Setup", $money_char. sprintf("%10.2f",$_->setup) ]; + if ( $cust_bill_pkg->setup != 0 ) { + push @buf, [ "$pkg Setup", + $money_char. sprintf("%10.2f", $cust_bill_pkg->setup) ]; push @buf, map { [ " ". $_->[0]. ": ". $_->[1], '' ] } $cust_pkg->labels; } - if ( $_->recur != 0 ) { + if ( $cust_bill_pkg->recur != 0 ) { push @buf, [ - "$pkg (" . time2str("%x",$_->sdate) . " - " . - time2str("%x",$_->edate) . ")", - $money_char. sprintf("%10.2f",$_->recur) + "$pkg (" . time2str("%x", $cust_bill_pkg->sdate) . " - " . + time2str("%x", $cust_bill_pkg->edate) . ")", + $money_char. sprintf("%10.2f", $cust_bill_pkg->recur) ]; push @buf, map { [ " ". $_->[0]. ": ". $_->[1], '' ] } $cust_pkg->labels; } + push @buf, map { [ " $_", '' ] } $cust_bill_pkg->details; + } else { #pkgnum tax - my $itemdesc = defined $_->dbdef_table->column('itemdesc') - ? ( $_->itemdesc || 'Tax' ) + my $itemdesc = defined $cust_bill_pkg->dbdef_table->column('itemdesc') + ? ( $cust_bill_pkg->itemdesc || 'Tax' ) : 'Tax'; - push @buf,[$itemdesc, $money_char. sprintf("%10.2f",$_->setup) ] - if $_->setup != 0; + push @buf, [ $itemdesc, + $money_char. sprintf("%10.2f", $cust_bill_pkg->setup) ] + if $cust_bill_pkg->setup != 0; } } @@ -1128,10 +1133,6 @@ sub print_text { =back -=head1 VERSION - -$Id: cust_bill.pm,v 1.61 2003-01-10 07:41:05 ivan Exp $ - =head1 BUGS The delete method. diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm index 5a1dcd2aa..a6615d05d 100644 --- a/FS/FS/cust_bill_pkg.pm +++ b/FS/FS/cust_bill_pkg.pm @@ -2,11 +2,12 @@ package FS::cust_bill_pkg; use strict; use vars qw( @ISA ); -use FS::Record qw( qsearchs ); +use FS::Record qw( qsearch qsearchs dbdef dbh ); use FS::cust_pkg; use FS::cust_bill; +use FS::cust_bill_pkg_detail; -@ISA = qw(FS::Record ); +@ISA = qw( FS::Record ); =head1 NAME @@ -73,6 +74,51 @@ sub table { 'cust_bill_pkg'; } Adds this line item to the database. If there is an error, returns the error, otherwise returns false. +=cut + +sub insert { + my $self = shift; + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + my $error = $self->SUPER::insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + unless ( defined dbdef->table('cust_bill_pkg_detail') && $self->get('details') ) { + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + return ''; + } + + foreach my $detail ( @{$self->get('details')} ) { + my $cust_bill_pkg_detail = new FS::cust_bill_pkg_detail { + 'pkgnum' => $self->pkgnum, + 'invnum' => $self->invnum, + 'detail' => $detail, + }; + $error = $cust_bill_pkg_detail->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; + +} + =item delete Currently unimplemented. I don't remove line items because there would then be @@ -139,11 +185,22 @@ sub cust_pkg { qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } ); } -=back +=item details + +Returns an array of detail information for the invoice line item. -=head1 VERSION +=cut -$Id: cust_bill_pkg.pm,v 1.4 2002-09-21 11:17:39 ivan Exp $ +sub details { + my $self = shift; + return () unless defined dbdef->table('cust_bill_pkg_detail'); + map { $_->detail } + qsearch ( 'cust_bill_pkg_detail', { 'pkgnum' => $self->pkgnum, + 'invnum' => $self->invnum, } ); + #qsearch ( 'cust_bill_pkg_detail', { 'lineitemnum' => $self->lineitemnum }); +} + +=back =head1 BUGS diff --git a/FS/FS/cust_bill_pkg_detail.pm b/FS/FS/cust_bill_pkg_detail.pm new file mode 100644 index 000000000..199de439b --- /dev/null +++ b/FS/FS/cust_bill_pkg_detail.pm @@ -0,0 +1,123 @@ +package FS::cust_bill_pkg_detail; + +use strict; +use vars qw( @ISA ); +use FS::Record qw( qsearch qsearchs ); + +@ISA = qw(FS::Record); + +=head1 NAME + +FS::cust_bill_pkg_detail - Object methods for cust_bill_pkg_detail records + +=head1 SYNOPSIS + + use FS::cust_bill_pkg_detail; + + $record = new FS::cust_bill_pkg_detail \%hash; + $record = new FS::cust_bill_pkg_detail { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::cust_bill_pkg_detail object represents additional detail information for +an invoice line item (see L). FS::cust_bill_pkg_detail +inherits from FS::Record. The following fields are currently supported: + +=over 4 + +=item detailnum - primary key + +=item pkgnum - + +=item invnum - + +=item detail - detail description + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new line item detail. To add the line item detail 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 + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'cust_bill_pkg_detail'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=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 + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid line item detail. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { + my $self = shift; + + $self->ut_numbern('detailnum') + || $self->ut_foreign_key('pkgnum', 'cust_pkg', 'pkgnum') + || $self->ut_foreign_key('invnum', 'cust_pkg', 'invnum') + || $self->ut_text('detail') + ; + +} + +=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 91ffa451a..807fadbcc 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -947,6 +947,8 @@ sub bill { my %hash = $cust_pkg->hash; my $old_cust_pkg = new FS::cust_pkg \%hash; + my @details = (); + # bill setup my $setup = 0; unless ( $cust_pkg->setup ) { @@ -1040,11 +1042,12 @@ sub bill { } if ( $setup > 0 || $recur > 0 ) { my $cust_bill_pkg = new FS::cust_bill_pkg ({ - 'pkgnum' => $cust_pkg->pkgnum, - 'setup' => $setup, - 'recur' => $recur, - 'sdate' => $sdate, - 'edate' => $cust_pkg->bill, + 'pkgnum' => $cust_pkg->pkgnum, + 'setup' => $setup, + 'recur' => $recur, + 'sdate' => $sdate, + 'edate' => $cust_pkg->bill, + 'details' => \@details, }); push @cust_bill_pkg, $cust_bill_pkg; $total_setup += $setup; diff --git a/FS/MANIFEST b/FS/MANIFEST index b3de623d7..e8b1da7a7 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -51,6 +51,7 @@ FS/agent.pm FS/agent_type.pm FS/cust_bill.pm FS/cust_bill_pkg.pm +FS/cust_bill_pkg_detail.pm FS/cust_credit.pm FS/cust_credit_bill.pm FS/cust_main.pm @@ -127,6 +128,7 @@ t/cust_bill.t t/cust_bill_event.t t/cust_bill_pay.t t/cust_bill_pkg.t +t/cust_bill_pkg_detail.t t/cust_credit.t t/cust_credit_bill.t t/cust_credit_refund.t diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup index 19483765e..cf009c249 100755 --- a/FS/bin/freeside-setup +++ b/FS/bin/freeside-setup @@ -421,6 +421,18 @@ sub tables_hash_hack { 'index' => [ ['invnum'] ], }, + 'cust_bill_pkg_detail' => { + 'columns' => [ + 'detailnum', 'serial', '', '', + 'pkgnum', 'int', '', '', + 'invnum', 'int', '', '', + 'detail', 'varchar', '', $char_d, + ], + 'primary_key' => 'detailnum', + 'unique' => [], + 'index' => [ [ 'pkgnum', 'invnum' ] ], + }, + 'cust_credit' => { 'columns' => [ 'crednum', 'serial', '', '', diff --git a/FS/t/cust_bill_pkg_detail.t b/FS/t/cust_bill_pkg_detail.t new file mode 100644 index 000000000..ea6e3d125 --- /dev/null +++ b/FS/t/cust_bill_pkg_detail.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::cust_bill_pkg_detail; +$loaded=1; +print "ok 1\n"; diff --git a/httemplate/docs/schema.html b/httemplate/docs/schema.html index b4d21f3b9..6522b041a 100644 --- a/httemplate/docs/schema.html +++ b/httemplate/docs/schema.html @@ -59,6 +59,13 @@
  • edate - ending date
  • itemdesc - Line item description (currently used only when pkgnum is 0) +
  • cust_bill_pkg_detail - Invoice line items detail +
      +
    • detailnum - primary key +
    • pkgnum - +
    • invnum - +
    • detail - Detail description +
  • cust_credit - Credits. The equivalent of a negative cust_bill record.
    • crednum - primary key diff --git a/httemplate/docs/upgrade10.html b/httemplate/docs/upgrade10.html new file mode 100644 index 000000000..7aa26f698 --- /dev/null +++ b/httemplate/docs/upgrade10.html @@ -0,0 +1,11 @@ +this is very incomplete + +CREATE TABLE cust_bill_pkg_detail ( + detailnum serial, + pkgnum int NOT NULL, + invnum int NOT NULL, + detail varchar(80), + PRIMARY KEY (detailnum) +); +CREATE INDEX cust_bill_pkg_detail1 ON cust_bill_pkg_detail ( pkgnum, invnum ); + diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi index 1fd634961..851d3aa4d 100755 --- a/httemplate/edit/part_pkg.cgi +++ b/httemplate/edit/part_pkg.cgi @@ -395,7 +395,7 @@ tie my %plans, 'Tie::IxHash', }, 'fieldorder' => [qw( setup_fee recur_flat recur_included_hours recur_hourly_charge recur_included_input recur_input_charge recur_included_output recur_output_charge recur_included_total recur_total_charge )], 'setup' => 'what.setup_fee.value', - 'recur' => '\'my $last_bill = $cust_pkg->last_bill; my $hours = $cust_pkg->seconds_since_sqlradacct($last_bill, $sdate ) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; my $input = $cust_pkg->attribute_since_sqlradacct($last_bill, $sdate, \"AcctInputOctets\" ) / 1048576; my $output = $cust_pkg->attribute_since_sqlradacct($last_bill, $sdate, \"AcctOutputOctets\" ) / 1048576; my $total = $input + $output - \' + what.recur_included_total.value + \'; $total = 0 if $total < 0; my $input = $input - \' + what.recur_included_input.value + \'; $input = 0 if $input < 0; my $output = $output - \' + what.recur_included_output.value + \'; $output = 0 if $output < 0; \' + what.recur_flat.value + \' + \' + what.recur_hourly_charge.value + \' * $hours + \' + what.recur_input_charge.value + \' * $input + \' + what.recur_output_charge.value + \' * $output + \' + what.recur_total_charge.value + \' * $total ;\'', + 'recur' => '\'my $last_bill = $cust_pkg->last_bill; my $hours = $cust_pkg->seconds_since_sqlradacct($last_bill, $sdate ) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; my $input = $cust_pkg->attribute_since_sqlradacct($last_bill, $sdate, \"AcctInputOctets\" ) / 1048576; my $output = $cust_pkg->attribute_since_sqlradacct($last_bill, $sdate, \"AcctOutputOctets\" ) / 1048576; my $total = $input + $output - \' + what.recur_included_total.value + \'; $total = 0 if $total < 0; my $input = $input - \' + what.recur_included_input.value + \'; $input = 0 if $input < 0; my $output = $output - \' + what.recur_included_output.value + \'; $output = 0 if $output < 0; my $totalcharge = sprintf(\"%.2f\", \' + what.recur_total_charge.value + \' * $total); my $hourscharge = sprintf(\"%.2f\", \' + what.recur_hourly_charge.value + \' * $hours); push @details, \"Last month\\\'s excess data \". sprintf(\"%.1f\", $total). \" megs: \\\$$totalcharge\", \"Last month\\\'s excess time \". sprintf(\"%.1f\", $hours). \" hours: \\\$$hourscharge\"; \' + what.recur_flat.value + \' + $hourscharge + \' + what.recur_input_charge.value + \' * $input + \' + what.recur_output_charge.value + \' * $output + $totalcharge ;\'', }, ; @@ -485,11 +485,11 @@ my $widget = new HTML::Widgets::SelectLayers( ''. 'Setup expression
      '. ''. + encode_entities($hashref->{setup}). '" onLoad="fchanged(this)">'. '

      '. 'Recurring espression
      '. ''. + encode_entities($hashref->{recur}). '" onLoad="fchanged(this)">'. '
      '. ''. '';