X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_main.pm;h=74015de34beaab0bf8c0b3c72e7a3e93031ffe4a;hb=243b248a929e99a9cc64e16f29e4a49afeb87a3c;hp=a9fcb2b6610f43867393ab32cf9e671b778657e7;hpb=c65b166b6e2ebdac5c2eb2e8336ebd1a4087f77c;p=freeside.git diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index a9fcb2b66..74015de34 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -1098,6 +1098,8 @@ sub bill { local $FS::UID::AutoCommit = 0; my $dbh = dbh; + $self->select_for_update; #mutex + # find the packages which are due for billing, find out how much they are # & generate invoice database. @@ -1499,6 +1501,8 @@ sub collect { local $FS::UID::AutoCommit = 0; my $dbh = dbh; + $self->select_for_update; #mutex + my $balance = $self->balance; warn "collect customer". $self->custnum. ": balance $balance" if $DEBUG; unless ( $balance > 0 ) { #redundant????? @@ -1701,7 +1705,7 @@ sub realtime_bop { #overrides $self->set( $_ => $options{$_} ) foreach grep { exists($options{$_}) } - qw( payname address1 address2 city state zip payinfo paydate ); + qw( payname address1 address2 city state zip payinfo paydate paycvv); #load up config my $bop_config = 'business-onlinepayment'; @@ -1711,6 +1715,9 @@ sub realtime_bop { $conf->config($bop_config); $action ||= 'normal authorization'; pop @bop_options if scalar(@bop_options) % 2 && $bop_options[-1] =~ /^\s*$/; + die "No real-time processor is enabled - ". + "did you set the business-onlinepayment configuration value?\n" + unless $processor; #massage data @@ -1837,11 +1844,12 @@ sub realtime_bop { } #remove paycvv after initial transaction - #make this disable-able via a config option if anyone insists? - # (though that probably violates cardholder agreements) + #false laziness w/misc/process/payment.cgi - check both to make sure working + # correctly if ( defined $self->dbdef_table->column('paycvv') && length($self->paycvv) && ! grep { $_ eq cardtype($self->payinfo) } $conf->config('cvv-save') + && ! length($options{'paycvv'}) ) { my $new = new FS::cust_main { $self->hash }; $new->paycvv(''); @@ -1871,15 +1879,19 @@ sub realtime_bop { } ); my $error = $cust_pay->insert; if ( $error ) { - # gah, even with transactions. - my $e = 'WARNING: Card/ACH debited but database not updated - '. - 'error applying payment, invnum #' . $self->invnum. - " ($processor): $error"; - warn $e; - return $e; - } else { - return ''; + $cust_pay->invnum(''); #try again with no specific invnum + my $error2 = $cust_pay->insert; + if ( $error2 ) { + # gah, even with transactions. + my $e = 'WARNING: Card/ACH debited but database not updated - '. + "error inserting payment ($processor): $error2". + " (previously tried insert with invnum #$options{'invnum'}" . + ": $error )"; + warn $e; + return $e; + } } + return ''; #no error } else { @@ -1888,7 +1900,7 @@ sub realtime_bop { if ( !$options{'quiet'} && !$realtime_bop_decline_quiet && $conf->exists('emaildecline') && grep { $_ ne 'POST' } $self->invoicing_list - && ! grep { $_ eq $transaction->error_message } + && ! grep { $transaction->error_message =~ /$_/ } $conf->config('emaildecline-exclude') ) { my @templ = $conf->config('declinetemplate'); @@ -2121,6 +2133,24 @@ sub balance_date { ); } +=item paydate_monthyear + +Returns a two-element list consisting of the month and year of this customer's +paydate (credit card expiration date for CARD customers) + +=cut + +sub paydate_monthyear { + my $self = shift; + if ( $self->paydate =~ /^(\d{4})-(\d{2})-\d{2}$/ ) { #Pg date format + ( $2, $1 ); + } elsif ( $self->paydate =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) { + ( $1, $3 ); + } else { + ('', ''); + } +} + =item invoicing_list [ ARRAYREF ] If an arguement is given, sets these email addresses as invoice recipients @@ -2451,6 +2481,18 @@ sub cust_refund { qsearch( 'cust_refund', { 'custnum' => $self->custnum } ) } +=item select_for_update + +Selects this record with the SQL "FOR UPDATE" command. This can be useful as +a mutex. + +=cut + +sub select_for_update { + my $self = shift; + qsearch('cust_main', { 'custnum' => $self->custnum }, '*', 'FOR UPDATE' ); +} + =back =head1 SUBROUTINES