allow blank auth for echeck refunds
[freeside.git] / FS / FS / cust_main.pm
index 58d1a28..075cce3 100644 (file)
@@ -13,6 +13,7 @@ BEGIN {
 }
 use Date::Format;
 #use Date::Manip;
+use String::Approx qw(amatch);
 use Business::CreditCard;
 use FS::UID qw( getotaker dbh );
 use FS::Record qw( qsearchs qsearch dbdef );
@@ -2067,13 +2068,13 @@ sub realtime_refund_bop {
 
   my $cust_pay = '';
   my $amount = $options{'amount'};
-  my( $pay_processor, $auth, $order_number );
+  my( $pay_processor, $auth, $order_number ) = ( '', '', '' );
   if ( $options{'paynum'} ) {
     warn "FS::cust_main::realtime_bop: paynum: $options{paynum}\n" if $DEBUG;
     $cust_pay = qsearchs('cust_pay', { paynum=>$options{'paynum'} } )
       or return "Unknown paynum $options{'paynum'}";
     $amount ||= $cust_pay->paid;
-    $cust_pay->paybatch =~ /^(\w+):(\w+)(:(\w+))?$/
+    $cust_pay->paybatch =~ /^(\w+):(\w*)(:(\w+))?$/
       or return "Can't parse paybatch for paynum $options{'paynum'}: ".
                 $cust_pay->paybatch;
     ( $pay_processor, $auth, $order_number ) = ( $1, $2, $4 );
@@ -2083,19 +2084,22 @@ sub realtime_refund_bop {
   }
   return "neither amount nor paynum specified" unless $amount;
 
+  my %content = (
+    'type'           => $method,
+    'login'          => $login,
+    'password'       => $password,
+    'order_number'   => $order_number,
+    'amount'         => $amount,
+    'referer'        => 'http://cleanwhisker.420.am/',
+  );
+  $content{authorization} = $auth
+    if length($auth); #echeck/ACH transactions have an order # but no auth
+                      #(at least with authorize.net)
+
   #first try void if applicable
   if ( $cust_pay && $cust_pay->paid == $amount ) { #and check dates?
     my $void = new Business::OnlinePayment( $processor, @bop_options );
-    $void->content(
-      'type'           => $method,
-      'action'         => 'void',
-      'login'          => $login,
-      'password'       => $password,
-      'order_number'   => $order_number,
-      'amount'         => $amount,
-      'authorization'  => $auth,
-      'referer'        => 'http://cleanwhisker.420.am/',
-    );
+    $void->content( 'action' => 'void', %content );
     $void->submit();
     if ( $void->is_success ) {
       my $error = $cust_pay->void($options{'reason'});
@@ -2126,7 +2130,6 @@ sub realtime_refund_bop {
     $payname =  "$payfirst $paylast";
   }
 
-  my %content = ();
   if ( $method eq 'CC' ) { 
 
     $content{card_number} = $self->payinfo;
@@ -2157,13 +2160,7 @@ sub realtime_refund_bop {
   #then try refund
   my $refund = new Business::OnlinePayment( $processor, @bop_options );
   $refund->content(
-    'type'           => $method,
     'action'         => 'credit',
-    'login'          => $login,
-    'password'       => $password,
-    'order_number'   => $order_number,
-    'amount'         => $amount,
-    'authorization'  => $auth,
     'customer_id'    => $self->custnum,
     'last_name'      => $paylast,
     'first_name'     => $payfirst,
@@ -2173,7 +2170,6 @@ sub realtime_refund_bop {
     'state'          => $self->state,
     'zip'            => $self->zip,
     'country'        => $self->country,
-    'referer'        => 'http://cleanwhisker.420.am/',
     %content, #after
   );
   $refund->submit();
@@ -2207,7 +2203,7 @@ sub realtime_refund_bop {
     'payby'    => $method2payby{$method},
     'payinfo'  => $self->payinfo,
     'paybatch' => $paybatch,
-    'reason'   => $options{'reason'} || 'card refund',
+    'reason'   => $options{'reason'} || 'card or ACH refund',
   } );
   my $error = $cust_refund->insert;
   if ( $error ) {
@@ -2949,6 +2945,42 @@ sub cancel_sql { "
           )
 "; }
 
+=item fuzzy_search FUZZY_HASHREF [ HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ ]
+
+Performs a fuzzy (approximate) search and returns the matching FS::cust_main
+records.  Currently, only I<last> or I<company> may be specified (the
+appropriate ship_ field is also searched if applicable).
+
+Additional options are the same as FS::Record::qsearch
+
+=cut
+
+sub fuzzy_search {
+  my( $self, $fuzzy, $hash, @opt) = @_;
+  #$self
+  $hash ||= {};
+  my @cust_main = ();
+
+  check_and_rebuild_fuzzyfiles();
+  foreach my $field ( keys %$fuzzy ) {
+    my $sub = \&{"all_$field"};
+    my %match = ();
+    $match{$_}=1 foreach ( amatch($fuzzy->{$field}, ['i'], @{ &$sub() } ) );
+
+    foreach ( keys %match ) {
+      push @cust_main, qsearch('cust_main', { %$hash, $field=>$_}, @opt);
+      push @cust_main, qsearch('cust_main', { %$hash, "ship_$field"=>$_}, @opt)
+        if defined dbdef->table('cust_main')->column('ship_last');
+    }
+  }
+
+  my %saw = ();
+  @cust_main = grep { !$saw{$_->custnum}++ } @cust_main;
+
+  @cust_main;
+
+}
+
 =back
 
 =head1 SUBROUTINES