X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2Fcust_bill.pm;h=0b8cb025418244de8020499990e5ec13cdd5aa67;hp=dad54348eac778ce46fef8799c0b18a730c89fa1;hb=82fca8a493a6490e385b40ebea690b29bf35bdbd;hpb=eccc8de2366e2e004a37761b8da2b447ec861ecb diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index dad54348e..0b8cb0254 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -1,8 +1,10 @@ package FS::cust_bill; -use base qw( FS::Template_Mixin FS::cust_main_Mixin FS::Record ); +use base qw( FS::cust_bill::Search FS::Template_Mixin + FS::cust_main_Mixin FS::Record + ); use strict; -use vars qw( $DEBUG $me $date_format ); +use vars qw( $DEBUG $me ); # but NOT $conf use Fcntl qw(:flock); #for spool_csv use Cwd; @@ -15,7 +17,6 @@ use GD::Barcode; use FS::UID qw( datasrc ); use FS::Misc qw( send_email send_fax do_print ); use FS::Record qw( qsearch qsearchs dbh ); -use FS::cust_main; use FS::cust_statement; use FS::cust_bill_pkg; use FS::cust_bill_pkg_display; @@ -25,12 +26,10 @@ use FS::cust_pay; use FS::cust_pkg; use FS::cust_credit_bill; use FS::pay_batch; -use FS::cust_pay_batch; use FS::cust_bill_event; use FS::cust_event; use FS::part_pkg; use FS::cust_bill_pay; -use FS::cust_bill_pay_batch; use FS::part_bill_event; use FS::payby; use FS::bill_batch; @@ -44,12 +43,6 @@ use FS::L10N; $DEBUG = 0; $me = '[FS::cust_bill]'; -#ask FS::UID to run this stuff for us later -FS::UID->install_callback( sub { - my $conf = new FS::Conf; #global - $date_format = $conf->config('date_format') || '%x'; #/YY -} ); - =head1 NAME FS::cust_bill - Object methods for cust_bill records @@ -80,7 +73,7 @@ FS::cust_bill - Object methods for cust_bill records $tax_amount = $record->tax; @lines = $cust_bill->print_text; - @lines = $cust_bill->print_text $time; + @lines = $cust_bill->print_text('time' => $time); =head1 DESCRIPTION @@ -106,21 +99,19 @@ L and L for conversion functions. =back -Customer info at invoice generation time +Deprecated fields =over 4 -=item previous_balance - -=item billing_balance - -=back - -Deprecated +=item billing_balance - the customer's balance immediately before generating +this invoice. DEPRECATED. Use the L method +to determine the customer's balance at a specific time. -=over 4 +=item previous_balance - the customer's balance immediately after generating +the invoice before this one. DEPRECATED. -=item printed - deprecated +=item printed - formerly used to track the number of times an invoice had +been printed; no longer used. =back @@ -136,6 +127,8 @@ Specific use cases =item promised_date - customer promised payment date, for collection +=item pending - invoice is still being generated, empty or 'Y' + =back =head1 METHODS @@ -151,9 +144,15 @@ Invoices are normally created by calling the bill method of a customer object =cut sub table { 'cust_bill'; } -sub notice_name { 'Invoice'; } -sub cust_linked { $_[0]->cust_main_custnum; } +# should be the ONLY occurrence of "Invoice" in invoice rendering code. +# (except email_subject and invnum_date_pretty) +sub notice_name { + my $self = shift; + $self->conf->config('notice_name') || 'Invoice' +} + +sub cust_linked { $_[0]->cust_main_custnum || $_[0]->custnum } sub cust_unlinked_msg { my $self = shift; "WARNING: can't find cust_main.custnum ". $self->custnum. @@ -339,6 +338,7 @@ sub replace_check { #return "Can't change _date!" unless $old->_date eq $new->_date; return "Can't change _date" unless $old->_date == $new->_date; return "Can't change charged" unless $old->charged == $new->charged + || $old->pending eq 'Y' || $old->charged == 0 || $new->{'Hash'}{'cc_surcharge_replace_hack'}; @@ -393,6 +393,7 @@ sub check { || $self->ut_enum('closed', [ '', 'Y' ]) || $self->ut_foreign_keyn('statementnum', 'cust_statement', 'statementnum' ) || $self->ut_numbern('agent_invid') #varchar? + || $self->ut_flag('pending') ; return $error if $error; @@ -412,14 +413,33 @@ cust_bill-default_agent_invid is set and it has a value, invnum otherwise. sub display_invnum { my $self = shift; - my $conf = $self->conf; - if ( $conf->exists('cust_bill-default_agent_invid') && $self->agent_invid ){ + if ( $self->agent_invid + && FS::Conf->new->exists('cust_bill-default_agent_invid') ) { return $self->agent_invid; } else { return $self->invnum; } } +=item previous_bill + +Returns the customer's last invoice before this one. + +=cut + +sub previous_bill { + my $self = shift; + if ( !$self->get('previous_bill') ) { + $self->set('previous_bill', qsearchs({ + 'table' => 'cust_bill', + 'hashref' => { 'custnum' => $self->custnum, + '_date' => { op=>'<', value=>$self->_date } }, + 'order_by' => 'ORDER BY _date DESC LIMIT 1', + }) ); + } + $self->get('previous_bill'); +} + =item previous Returns a list consisting of the total previous balance for this customer, @@ -465,7 +485,9 @@ sub cust_bill_pkg { qsearch( { 'table' => 'cust_bill_pkg', 'hashref' => { 'invnum' => $self->invnum }, - 'order_by' => 'ORDER BY billpkgnum', + 'order_by' => 'ORDER BY billpkgnum', #important? otherwise we could use + # the AUTLOADED FK search. or should + # that default to ORDER by the pkey? } ); } @@ -607,11 +629,21 @@ sub num_cust_event { Returns the customer (see L) for this invoice. +=item suspend + +Suspends all unsuspended packages (see L) for this invoice + +Returns a list: an empty list on success or a list of errors. + =cut -sub cust_main { +sub suspend { my $self = shift; - qsearchs( 'cust_main', { 'custnum' => $self->custnum } ); + + grep { $_->suspend(@_) } + grep {! $_->getfield('cancel') } + $self->cust_pkg; + } =item cust_suspend_if_balance_over AMOUNT @@ -633,55 +665,34 @@ sub cust_suspend_if_balance_over { } } -=item cust_credit +=item cancel -Depreciated. See the cust_credited method. - - #Returns a list consisting of the total previous credited (see - #L) and unapplied for this customer, followed by the previous - #outstanding credits (FS::cust_credit objects). +Cancel the packages on this invoice. Largely similar to the cust_main version, but does not bother yet with banned payment options =cut -sub cust_credit { - use Carp; - croak "FS::cust_bill->cust_credit depreciated; see ". - "FS::cust_bill->cust_credit_bill"; - #my $self = shift; - #my $total = 0; - #my @cust_credit = sort { $a->_date <=> $b->_date } - # grep { $_->credited != 0 && $_->_date < $self->_date } - # qsearch('cust_credit', { 'custnum' => $self->custnum } ) - #; - #foreach (@cust_credit) { $total += $_->credited; } - #$total, @cust_credit; -} - -=item cust_pay - -Depreciated. See the cust_bill_pay method. +sub cancel { + my( $self, %opt ) = @_; -#Returns all payments (see L) for this invoice. + warn "$me cancel called on cust_bill ". $self->invnum . " with options ". + join(', ', map { "$_: $opt{$_}" } keys %opt ). "\n" + if $DEBUG; -=cut + return ( 'access denied' ) + unless $FS::CurrentUser::CurrentUser->access_right('Cancel customer'); -sub cust_pay { - use Carp; - croak "FS::cust_bill->cust_pay depreciated; see FS::cust_bill->cust_bill_pay"; - #my $self = shift; - #sort { $a->_date <=> $b->_date } - # qsearch( 'cust_pay', { 'invnum' => $self->invnum } ) - #; -} + my @pkgs = $self->cust_pkg; -sub cust_pay_batch { - my $self = shift; - qsearch('cust_pay_batch', { 'invnum' => $self->invnum } ); -} + if ( !$opt{nobill} && $conf->exists('bill_usage_on_cancel') ) { + $opt{nobill} = 1; + my $error = $self->cust_main->bill( pkg_list => [ @pkgs ], cancel => 1 ); + warn "Error billing during cancel, custnum ". $self->custnum. ": $error" + if $error; + } -sub cust_bill_pay_batch { - my $self = shift; - qsearch('cust_bill_pay_batch', { 'invnum' => $self->invnum } ); + grep { $_ } map { $_->cancel(%opt) } + grep {! $_->getfield('cancel') } + @pkgs; } =item cust_bill_pay @@ -1022,7 +1033,7 @@ Options: sender address, required -=item tempate +=item template alternate template name, optional @@ -1056,15 +1067,12 @@ sub generate_email { my %return = ( 'from' => $args{'from'}, - 'subject' => (($args{'subject'}) ? $args{'subject'} : 'Invoice'), + 'subject' => ($args{'subject'} || $self->email_subject), + 'custnum' => $self->custnum, + 'msgtype' => 'invoice', ); - my %opt = ( - 'unsquelch_cdr' => $conf->exists('voip-cdr_email'), - 'template' => $args{'template'}, - 'notice_name' => ( $args{'notice_name'} || 'Invoice' ), - 'no_coupon' => $args{'no_coupon'}, - ); + $args{'unsquelch_cdr'} = $conf->exists('voip-cdr_email'); my $cust_main = $self->cust_main; @@ -1106,7 +1114,7 @@ sub generate_email { if ( ref($args{'print_text'}) eq 'ARRAY' ) { $data = $args{'print_text'}; } else { - $data = [ $self->print_text(\%opt) ]; + $data = [ $self->print_text(\%args) ]; } } @@ -1114,6 +1122,7 @@ sub generate_email { $alternative->attach( 'Type' => 'text/plain', 'Encoding' => 'quoted-printable', + 'Charset' => 'UTF-8', #'Encoding' => '7bit', 'Data' => $data, 'Disposition' => 'inline', @@ -1163,10 +1172,10 @@ sub generate_email { 'Filename' => 'barcode.png', 'Content-ID' => "<$barcode_content_id>", ; - $opt{'barcode_cid'} = $barcode_content_id; + $args{'barcode_cid'} = $barcode_content_id; } - $htmldata = $self->print_html({ 'cid'=>$content_id, %opt }); + $htmldata = $self->print_html({ 'cid'=>$content_id, %args }); } $alternative->attach( @@ -1228,7 +1237,7 @@ sub generate_email { $related->add_part($image) if $image; - my $pdf = build MIME::Entity $self->mimebuild_pdf(\%opt); + my $pdf = build MIME::Entity $self->mimebuild_pdf(\%args); $return{'mimeparts'} = [ $related, $pdf, @otherparts ]; @@ -1260,7 +1269,7 @@ sub generate_email { #mime parts arguments a la MIME::Entity->build(). $return{'mimeparts'} = [ - { $self->mimebuild_pdf(\%opt) } + { $self->mimebuild_pdf(\%args) } ]; } @@ -1280,7 +1289,7 @@ sub generate_email { if ( ref($args{'print_text'}) eq 'ARRAY' ) { $return{'body'} = $args{'print_text'}; } else { - $return{'body'} = [ $self->print_text(\%opt) ]; + $return{'body'} = [ $self->print_text(\%args) ]; } } @@ -1309,99 +1318,48 @@ sub mimebuild_pdf { ); } -=item send HASHREF | [ TEMPLATE [ , AGENTNUM [ , INVOICE_FROM [ , AMOUNT ] ] ] ] +=item send HASHREF Sends this invoice to the destinations configured for this customer: sends email, prints and/or faxes. See L. -Options can be passed as a hashref (recommended) or as a list of up to -four values for templatename, agentnum, invoice_from and amount. - -I