X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_bill.pm;h=79f85c8070398bf13b75e4c9b4263381e21133af;hb=35f9c8a5ed701f9e9362d69084f2f334b8634a5c;hp=4acdd85a3e0a1ef3a8a4ba878178fae2008cab9e;hpb=4396080ed2829ae0595f1fd777f39d090c9bcd7c;p=freeside.git diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 4acdd85a3..79f85c807 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -16,6 +16,7 @@ use FS::Misc qw( send_email send_fax generate_ps generate_pdf do_print ); use FS::Record qw( qsearch qsearchs dbh ); use FS::cust_main_Mixin; use FS::cust_main; +use FS::cust_statement; use FS::cust_bill_pkg; use FS::cust_bill_pkg_display; use FS::cust_credit; @@ -82,6 +83,8 @@ owes you money. The specific charges are itemized as B records (see L). FS::cust_bill inherits from FS::Record. The following fields are currently supported: +Regular fields + =over 4 =item invnum - primary key (assigned automatically for new invoices) @@ -93,10 +96,26 @@ L and L for conversion functions. =item charged - amount of this invoice +=back + +Deprecated + +=over 4 + =item printed - deprecated +=back + +Specific use cases + +=over 4 + =item closed - books closed flag, empty or `Y' +=item statementnum - invoice aggregation (see L) + +=item agent_invid - legacy invoice number + =back =head1 METHODS @@ -183,17 +202,16 @@ sub check { my $error = $self->ut_numbern('invnum') - || $self->ut_number('custnum') + || $self->ut_foreign_key('custnum', 'cust_main', 'custnum' ) || $self->ut_numbern('_date') || $self->ut_money('charged') || $self->ut_numbern('printed') || $self->ut_enum('closed', [ '', 'Y' ]) + || $self->ut_foreign_keyn('statementnum', 'cust_statement', 'statementnum' ) + || $self->ut_numbern('agent_invid') #varchar? ; return $error if $error; - return "Unknown customer" - unless qsearchs( 'cust_main', { 'custnum' => $self->custnum } ); - $self->_date(time) unless $self->_date; $self->printed(0) if $self->printed eq ''; @@ -201,6 +219,22 @@ sub check { $self->SUPER::check; } +=item display_invnum + +Returns the displayed invoice number for this invoice: agent_invid if +cust_bill-default_agent_invid is set and it has a value, invnum otherwise. + +=cut + +sub display_invnum { + my $self = shift; + if ( $conf->exists('cust_bill-default_agent_invid') && $self->agent_invid ){ + return $self->agent_invid; + } else { + return $self->invnum; + } +} + =item previous Returns a list consisting of the total previous balance for this customer, @@ -451,7 +485,7 @@ sub cust_credited { ; } -=item cust_bill_pay_pkgnum +=item cust_bill_pay_pkgnum PKGNUM Returns all payment applications (see L) for this invoice with matching pkgnum. @@ -467,7 +501,7 @@ sub cust_bill_pay_pkgnum { ); } -=item cust_credited_pkgnum +=item cust_credited_pkgnum PKGNUM Returns all applied credits (see L) for this invoice with matching pkgnum. @@ -531,12 +565,20 @@ sub owed_pkgnum { $balance; } -=item apply_payments_and_credits +=item apply_payments_and_credits [ OPTION => VALUE ... ] + +Applies unapplied payments and credits to this invoice. + +A hash of optional arguments may be passed. Currently "manual" is supported. +If true, a payment receipt is sent instead of a statement when +'payment_receipt_email' configuration option is set. + +If there is an error, returns the error, otherwise returns false. =cut sub apply_payments_and_credits { - my $self = shift; + my( $self, %options ) = @_; local $SIG{HUP} = 'IGNORE'; local $SIG{INT} = 'IGNORE'; @@ -628,12 +670,12 @@ sub apply_payments_and_credits { } next unless $owed > 0; - warn "min ( $unapp_amount, $owed )\n"; + warn "min ( $unapp_amount, $owed )\n" if $DEBUG; $app->amount( sprintf('%.2f', min( $unapp_amount, $owed ) ) ); $app->invnum( $self->invnum ); - my $error = $app->insert; + my $error = $app->insert(%options); if ( $error ) { $dbh->rollback if $oldAutoCommit; return "Error inserting ". $app->table. " record: $error"; @@ -794,8 +836,11 @@ sub generate_email { push @otherparts, build MIME::Entity 'Type' => 'text/csv', 'Encoding' => '7bit', - 'Data' => [ map { "$_\n" } $self->call_details ], + 'Data' => [ map { "$_\n" } + $self->call_details('prepend_billed_number' => 1) + ], 'Disposition' => 'attachment', + 'Filename' => 'usage-'. $self->invnum. '.csv', ; } @@ -1812,7 +1857,7 @@ sub print_generic { my( $self, %params ) = @_; my $today = $params{today} ? $params{today} : time; - warn "FS::cust_bill::print_generic called on $self with suffix $params{template}\n" + warn "$me print_generic called on $self with suffix $params{template}\n" if $DEBUG; my $format = $params{format}; @@ -2163,7 +2208,7 @@ sub print_generic { $invoice_data{'total_items'} = \@total_items; $invoice_data{'buf'} = \@buf; $invoice_data{'sections'} = \@sections; - + my $previous_section = { 'description' => 'Previous Charges', 'subtotal' => $other_money_char. sprintf('%.2f', $pr_total), @@ -2336,7 +2381,7 @@ sub print_generic { } } $invoice_data{'taxtotal'} = sprintf('%.2f', $taxtotal); - + push @buf,['','-----------']; push @buf,[( $conf->exists('disable_previous_balance') ? 'Total Charges' @@ -2411,7 +2456,7 @@ sub print_generic { foreach my $credit ( $self->_items_credits('trim_len'=>32) ) { push @buf, [ $credit->{'description'}, $money_char.$credit->{'amount'} ]; } - + # payments my $paymenttotal = 0; foreach my $payment ( $self->_items_payments ) { @@ -2920,8 +2965,6 @@ sub _items_cust_bill_pkg { my $type = $display->type; - my $cust_pkg = $cust_bill_pkg->cust_pkg; - my $desc = $cust_bill_pkg->desc; $desc = substr($desc, 0, 50). '...' if $format eq 'latex' && length($desc) > 50; @@ -2933,6 +2976,8 @@ sub _items_cust_bill_pkg { if ( $cust_bill_pkg->pkgnum > 0 ) { + my $cust_pkg = $cust_bill_pkg->cust_pkg; + if ( $cust_bill_pkg->setup != 0 && (!$type || $type eq 'S') ) { my $description = $desc; @@ -3129,20 +3174,36 @@ sub _items_payments { } -=item call_details +=item call_details [ OPTION => VALUE ... ] Returns an array of CSV strings representing the call details for this invoice +The only option available is the boolean prepend_billed_number =cut sub call_details { - my $self = shift; - map { $_->details( 'format_function' => sub{ shift }, - 'escape_function' => sub{ return() }, - ) - } - grep { $_->pkgnum } - $self->cust_bill_pkg; + my ($self, %opt) = @_; + + my $format_function = sub { shift }; + + if ($opt{prepend_billed_number}) { + $format_function = sub { + my $detail = shift; + my $row = shift; + + $row->amount ? $row->phonenum. ",". $detail : '"Billed number",'. $detail; + + }; + } + + my @details = map { $_->details( 'format_function' => $format_function, + 'escape_function' => sub{ return() }, + ) + } + grep { $_->pkgnum } + $self->cust_bill_pkg; + my $header = $details[0]; + ( $header, grep { $_ ne $header } @details ); }