X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_bill.pm;h=2c0b35388a912429a75c5fca71831ad545d4dadf;hb=1d15d22917b9e91fbb9b5a195f94bf3b71fe304a;hp=1656658ca4661aa45a4e89f848c617688c5110e1;hpb=9811b8ce65909a293810ddbcd8c9b5ca963fba01;p=freeside.git diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 1656658ca..2c0b35388 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -4,6 +4,7 @@ use strict; use vars qw( @ISA $DEBUG $me $conf $money_char ); use vars qw( $invoice_lines @buf ); #yuck use Fcntl qw(:flock); #for spool_csv +use List::Util qw(min max); use IPC::Run3; use Date::Format; use Text::Template 1.20; @@ -228,6 +229,20 @@ sub cust_bill_pkg { qsearch( 'cust_bill_pkg', { 'invnum' => $self->invnum } ); } +=item cust_pkg + +Returns the packages (see L) corresponding to the line items for +this invoice. + +=cut + +sub cust_pkg { + my $self = shift; + my @cust_pkg = map { $_->cust_pkg } $self->cust_bill_pkg; + my %saw = (); + grep { ! $saw{$_->pkgnum}++ } @cust_pkg; +} + =item open_cust_bill_pkg Returns the open line items for this invoice. @@ -397,6 +412,79 @@ sub owed { $balance; } +=item apply_payments_and_credits + +=cut + +sub apply_payments_and_credits { + my $self = shift; + + my @payments = grep { $_->unapplied > 0 } $self->cust_main->cust_pay; + my @credits = grep { $_->credited > 0 } $self->cust_main->cust_credit; + + while ( $self->owed > 0 and ( @payments || @credits ) ) { + + my $app = ''; + if ( @payments && @credits ) { + + #decide which goes first by weight of top (unapplied) line item + + my @open_lineitems = $self->open_cust_bill_pkg; + + my $max_pay_weight = + max( map { $_->cust_pkg->part_pkg->pay_weight || 0 } + @open_lineitems + ); + my $max_credit_weight = + max( map { $_->cust_pkg->part_pkg->credit_weight || 0 } + @open_lineitems + ); + + #if both are the same... payments first? it has to be something + if ( $max_pay_weight >= $max_credit_weight ) { + $app = 'pay'; + } else { + $app = 'credit'; + } + + } elsif ( @payments ) { + $app = 'pay'; + } elsif ( @credits ) { + $app = 'credit'; + } else { + die "guru meditation #12 and 35"; + } + + if ( $app eq 'pay' ) { + + my $payment = shift @payments; + + $app = new FS::cust_bill_pay { + 'paynum' => $payment->paynum, + 'amount' => sprintf('%.2f', min( $payment->unapplied, $self->owed ) ), + }; + + } elsif ( $app eq 'credit' ) { + + my $credit = shift @credits; + + $app = new FS::cust_credit_bill { + 'crednum' => $credit->crednum, + 'amount' => sprintf('%.2f', min( $credit->credited, $self->owed ) ), + }; + + } else { + die "guru meditation #12 and 35"; + } + + $app->invnum( $self->invnum ); + + my $error = $app->insert; + die $error if $error; + + } + +} =item generate_email PARAMHASH @@ -483,16 +571,17 @@ sub generate_email { 'Disposition' => 'inline', ); - $args{'from'} =~ /\@([\w\.\-]+)/ or $1 = 'example.com'; - my $content_id = join('.', rand()*(2**32), $$, time). "\@$1"; + $args{'from'} =~ /\@([\w\.\-]+)/; + my $from = $1 || 'example.com'; + my $content_id = join('.', rand()*(2**32), $$, time). "\@$from"; my $path = "$FS::UID::conf_dir/conf.$FS::UID::datasrc"; my $file; - if ( defined($args{'_template'}) && length($args{'_template'}) - && -e "$path/logo_". $args{'_template'}. ".png" + if ( defined($args{'template'}) && length($args{'template'}) + && -e "$path/logo_". $args{'template'}. ".png" ) { - $file = "$path/logo_". $args{'_template'}. ".png"; + $file = "$path/logo_". $args{'template'}. ".png"; } else { $file = "$path/logo.png"; } @@ -640,6 +729,21 @@ INVOICE_FROM, if specified, overrides the default email invoice From: address. =cut +sub queueable_send { + my %opt = @_; + + my $self = qsearchs('cust_bill', { 'invnum' => $opt{invnum} } ) + or die "invalid invoice number: " . $opt{invnum}; + + my @args = ( $opt{template}, $opt{agentnum} ); + push @args, $opt{invoice_from} + if exists($opt{invoice_from}) && $opt{invoice_from}; + + my $error = $self->send( @args ); + die $error if $error; + +} + sub send { my $self = shift; my $template = scalar(@_) ? shift : ''; @@ -678,6 +782,21 @@ INVOICE_FROM, if specified, overrides the default email invoice From: address. =cut +sub queueable_email { + my %opt = @_; + + my $self = qsearchs('cust_bill', { 'invnum' => $opt{invnum} } ) + or die "invalid invoice number: " . $opt{invnum}; + + my @args = ( $opt{template} ); + push @args, $opt{invoice_from} + if exists($opt{invoice_from}) && $opt{invoice_from}; + + my $error = $self->email( @args ); + die $error if $error; + +} + sub email { my $self = shift; my $template = scalar(@_) ? shift : ''; @@ -1628,12 +1747,14 @@ sub print_text { #setup template variables package FS::cust_bill::_template; #! - use vars qw( $invnum $date $page $total_pages @address $overdue @buf $agent ); + use vars qw( $custnum $invnum $date $agent @address $overdue + $page $total_pages @buf ); + $custnum = $self->custnum; $invnum = $self->invnum; $date = $self->_date; - $page = 1; $agent = $self->cust_main->agent->agent; + $page = 1; if ( $FS::cust_bill::invoice_lines ) { $total_pages = @@ -1766,6 +1887,7 @@ sub print_latex { } my %invoice_data = ( + 'custnum' => $self->custnum, 'invnum' => $self->invnum, 'date' => time2str('%b %o, %Y', $self->_date), 'today' => time2str('%b %o, %Y', $today), @@ -2166,6 +2288,7 @@ sub print_html { or die 'While compiling ' . $templatefile . ': ' . $Text::Template::ERROR; my %invoice_data = ( + 'custnum' => $self->custnum, 'invnum' => $self->invnum, 'date' => time2str('%b %o, %Y', $self->_date), 'today' => time2str('%b %o, %Y', $today), @@ -2227,6 +2350,7 @@ sub print_html { s/\\item /
  • /; s/\\end\{enumerate\}/<\/ol>/; s/\\textbf\{(.*)\}/$1<\/b>/; + s/\\\\\*/ /; $_; } $conf->config_orbase('invoice_latexnotes', $template)