add methods for masking credit cards, add payment info modification to self-service
[freeside.git] / FS / FS / cust_main.pm
index 59e3570..ad5b0df 100644 (file)
@@ -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?????
@@ -1875,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 {
 
@@ -2143,6 +2151,19 @@ sub paydate_monthyear {
   }
 }
 
+=item payinfo_masked
+
+Returns a "masked" payinfo field with all but the last four characters replaced
+by 'x'es.  Useful for displaying credit cards.
+
+=cut
+
+sub payinfo_masked {
+  my $self = shift;
+  my $payinfo = $self->payinfo;
+  'x'x(length($payinfo)-4). substr($payinfo,(length($payinfo)-4));
+}
+
 =item invoicing_list [ ARRAYREF ]
 
 If an arguement is given, sets these email addresses as invoice recipients
@@ -2473,6 +2494,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
@@ -2824,6 +2857,8 @@ card types.
 
 No multiple currency support (probably a larger project than just this module).
 
+payinfo_masked false laziness with cust_pay.pm and cust_refund.pm
+
 =head1 SEE ALSO
 
 L<FS::Record>, L<FS::cust_pkg>, L<FS::cust_bill>, L<FS::cust_credit>