X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_bill.pm;h=1656658ca4661aa45a4e89f848c617688c5110e1;hb=33f61386d77a035fd59a15ccfea43d0fbff911d2;hp=def84f91a5e1c47dd01f54ff94639d9f51ac51b1;hpb=580330233cbf32c58d9f29dc391bd2ebd83e16d5;p=freeside.git diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index def84f91a..1656658ca 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -1,7 +1,7 @@ package FS::cust_bill; use strict; -use vars qw( @ISA $DEBUG $conf $money_char ); +use vars qw( @ISA $DEBUG $me $conf $money_char ); use vars qw( $invoice_lines @buf ); #yuck use Fcntl qw(:flock); #for spool_csv use IPC::Run3; @@ -26,11 +26,14 @@ use FS::cust_pay_batch; use FS::cust_bill_event; use FS::part_pkg; use FS::cust_bill_pay; +use FS::cust_bill_pay_batch; use FS::part_bill_event; +use FS::payby; @ISA = qw( FS::cust_main_Mixin FS::Record ); $DEBUG = 0; +$me = '[FS::cust_bill]'; #ask FS::UID to run this stuff for us later FS::UID->install_callback( sub { @@ -225,6 +228,33 @@ sub cust_bill_pkg { qsearch( 'cust_bill_pkg', { 'invnum' => $self->invnum } ); } +=item open_cust_bill_pkg + +Returns the open line items for this invoice. + +Note that cust_bill_pkg with both setup and recur fees are returned as two +separate line items, each with only one fee. + +=cut + +# modeled after cust_main::open_cust_bill +sub open_cust_bill_pkg { + my $self = shift; + + # grep { $_->owed > 0 } $self->cust_bill_pkg + + my %other = ( 'recur' => 'setup', + 'setup' => 'recur', ); + my @open = (); + foreach my $field ( qw( recur setup )) { + push @open, map { $_->set( $other{$field}, 0 ); $_; } + grep { $_->owed($field) > 0 } + $self->cust_bill_pkg; + } + + @open; +} + =item cust_bill_event Returns the completed invoice events (see L) for this @@ -264,7 +294,7 @@ sub cust_suspend_if_balance_over { if ( $cust_main->total_owed_date($self->_date) < $amount ) { return (); } else { - $cust_main->suspend; + $cust_main->suspend(@_); } } @@ -1273,26 +1303,44 @@ sub realtime_bop { } -=item batch_card +=item batch_card OPTION => VALUE... Adds a payment for this invoice to the pending credit card batch (see -L). +L), or, if the B option is set to a true value, +runs the payment using a realtime gateway. =cut sub batch_card { - my $self = shift; + my ($self, %options) = @_; my $cust_main = $self->cust_main; + my $amount = sprintf("%.2f", $cust_main->balance - $cust_main->in_transit_payments); + return '' unless $amount > 0; + + if ($options{'realtime'}) { + return $cust_main->realtime_bop( FS::payby->payby2bop($cust_main->payby), + $amount, + %options, + ); + } + my $oldAutoCommit = $FS::UID::AutoCommit; local $FS::UID::AutoCommit = 0; my $dbh = dbh; - my $pay_batch = qsearchs('pay_batch', {'status' => 'O'}); + $dbh->do("LOCK TABLE pay_batch IN SHARE ROW EXCLUSIVE MODE") + or return "Cannot lock pay_batch: " . $dbh->errstr; + + my %pay_batch = ( + 'status' => 'O', + 'payby' => FS::payby->payby2payment($cust_main->payby), + ); + + my $pay_batch = qsearchs( 'pay_batch', \%pay_batch ); unless ( $pay_batch ) { - $pay_batch = new FS::pay_batch; - $pay_batch->setfield('status' => 'O'); + $pay_batch = new FS::pay_batch \%pay_batch; my $error = $pay_batch->insert; if ( $error ) { $dbh->rollback if $oldAutoCommit; @@ -1300,29 +1348,72 @@ sub batch_card { } } + my $old_cust_pay_batch = qsearchs('cust_pay_batch', { + 'batchnum' => $pay_batch->batchnum, + 'custnum' => $cust_main->custnum, + } ); + my $cust_pay_batch = new FS::cust_pay_batch ( { - 'batchnum' => $pay_batch->getfield('batchnum'), - 'invnum' => $self->getfield('invnum'), - 'custnum' => $cust_main->getfield('custnum'), + 'batchnum' => $pay_batch->batchnum, + 'invnum' => $self->getfield('invnum'), # is there a better value? + # this field should be + # removed... + # cust_bill_pay_batch now + 'custnum' => $cust_main->custnum, 'last' => $cust_main->getfield('last'), 'first' => $cust_main->getfield('first'), - 'address1' => $cust_main->getfield('address1'), - 'address2' => $cust_main->getfield('address2'), - 'city' => $cust_main->getfield('city'), - 'state' => $cust_main->getfield('state'), - 'zip' => $cust_main->getfield('zip'), - 'country' => $cust_main->getfield('country'), + 'address1' => $cust_main->address1, + 'address2' => $cust_main->address2, + 'city' => $cust_main->city, + 'state' => $cust_main->state, + 'zip' => $cust_main->zip, + 'country' => $cust_main->country, + 'payby' => $cust_main->payby, 'payinfo' => $cust_main->payinfo, - 'exp' => $cust_main->getfield('paydate'), - 'payname' => $cust_main->getfield('payname'), - 'amount' => $self->owed, + 'exp' => $cust_main->paydate, + 'payname' => $cust_main->payname, + 'amount' => $amount, # consolidating } ); - my $error = $cust_pay_batch->insert; + + $cust_pay_batch->paybatchnum($old_cust_pay_batch->paybatchnum) + if $old_cust_pay_batch; + + my $error; + if ($old_cust_pay_batch) { + $error = $cust_pay_batch->replace($old_cust_pay_batch) + } else { + $error = $cust_pay_batch->insert; + } + if ( $error ) { $dbh->rollback if $oldAutoCommit; die $error; } + my $unapplied = $cust_main->total_credited + $cust_main->total_unapplied_payments + $cust_main->in_transit_payments; + foreach my $cust_bill ($cust_main->open_cust_bill) { + #$dbh->commit or die $dbh->errstr if $oldAutoCommit; + my $cust_bill_pay_batch = new FS::cust_bill_pay_batch { + 'invnum' => $cust_bill->invnum, + 'paybatchnum' => $cust_pay_batch->paybatchnum, + 'amount' => $cust_bill->owed, + '_date' => time, + }; + if ($unapplied >= $cust_bill_pay_batch->amount){ + $unapplied -= $cust_bill_pay_batch->amount; + next; + }else{ + $cust_bill_pay_batch->amount(sprintf ( "%.2f", + $cust_bill_pay_batch->amount - $unapplied )); + $unapplied = 0; + } + $error = $cust_bill_pay_batch->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + die $error; + } + } + $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; }