Merge branch 'master' of git.freeside.biz:/home/git/freeside
[freeside.git] / FS / FS / cust_main / Search.pm
index e0c7080..182527f 100644 (file)
@@ -9,6 +9,7 @@ use FS::Record qw( qsearch );
 use FS::cust_main;
 use FS::cust_main_invoice;
 use FS::svc_acct;
+use FS::payinfo_Mixin;
 
 @EXPORT_OK = qw( smart_search );
 
@@ -50,8 +51,12 @@ FS::cust_main::Search - Customer searching
 
 Accepts the following options: I<search>, the string to search for.  The string
 will be searched for as a customer number, phone number, name or company name,
-as an exact, or, in some cases, a substring or fuzzy match (see the source code
-for the exact heuristics used); I<no_fuzzy_on_exact>, causes smart_search to
+address (if address1-search is on), invoicing email address, or credit card
+number.
+
+Searches match as an exact, or, in some cases, a substring or fuzzy match (see
+the source code for the exact heuristics used); I<no_fuzzy_on_exact>, causes
+smart_search to
 skip fuzzy matching when an exact match is found.
 
 Any additional options are treated as an additional qualifier on the search
@@ -109,12 +114,10 @@ sub smart_search {
 
     }
 
-  # custnum search (also try agent_custid), with some tweaking options if your
-  # legacy cust "numbers" have letters
   } 
   
   
-  if ( $search =~ /@/ ) {
+  if ( $search =~ /@/ ) { #invoicing email address
       push @cust_main,
          map $_->cust_main,
              qsearch( {
@@ -122,6 +125,9 @@ sub smart_search {
                         'hashref'   => { 'dest' => $search },
                       }
                     );
+
+  # custnum search (also try agent_custid), with some tweaking options if your
+  # legacy cust "numbers" have letters
   } elsif ( $search =~ /^\s*(\d+)\s*$/
          || ( $conf->config('cust_main-agent_custid-format') eq 'ww?d+'
               && $search =~ /^\s*(\w\w?\d+)\s*$/
@@ -364,6 +370,28 @@ sub smart_search {
 
   }
 
+  ( my $nospace_search = $search ) =~ s/\s//g;
+  ( my $card_search = $nospace_search ) =~ s/\-//g;
+  $card_search =~ s/[x\*\.\_]/x/gi;
+  
+  if ( $card_search =~ /^[\dx]{15,16}$/i ) { #credit card search
+
+    ( my $like_search = $card_search ) =~ s/x/_/g;
+    my $mask_search = FS::payinfo_Mixin->mask_payinfo('CARD', $card_search);
+
+    push @cust_main, qsearch({
+      'table'     => 'cust_main',
+      'hashref'   => {},
+      'extra_sql' => " WHERE (    payinfo LIKE '$like_search'
+                               OR paymask =    '$mask_search'
+                             ) ".
+                     " AND payby IN ('CARD','DCRD') ".
+                     " AND $agentnums_sql", #agent virtulization
+    });
+
+  }
+  
+
   #eliminate duplicates
   my %saw = ();
   @cust_main = grep { !$saw{$_->custnum}++ } @cust_main;
@@ -551,7 +579,16 @@ sub search {
   }
 
   ##
-  # do the same for user
+  # parse sales person
+  ##
+
+  if ( $params->{'salesnum'} =~ /^(\d+)$/ ) {
+    push @where, ($1 > 0 ) ? "cust_main.salesnum = $1"
+                           : 'cust_main.salesnum IS NULL';
+  }
+
+  ##
+  # parse usernum
   ##
 
   if ( $params->{'usernum'} =~ /^(\d+)$/ and $1 ) {
@@ -573,14 +610,24 @@ sub search {
   ##
   # address
   ##
-  if ( $params->{'address'} =~ /\S/ ) {
-    my $address = dbh->quote('%'. lc($params->{'address'}). '%');
-    push @where, "EXISTS(
-      SELECT 1 FROM cust_location 
-      WHERE cust_location.custnum = cust_main.custnum
-        AND (LOWER(cust_location.address1) LIKE $address OR
-             LOWER(cust_location.address2) LIKE $address)
-    )";
+  if ( $params->{'address'} ) {
+    # allow this to be an arrayref
+    my @values = ($params->{'address'});
+    @values = @{$values[0]} if ref($values[0]);
+    my @orwhere;
+    foreach (grep /\S/, @values) {
+      my $address = dbh->quote('%'. lc($_). '%');
+      push @orwhere,
+        "LOWER(cust_location.address1) LIKE $address",
+        "LOWER(cust_location.address2) LIKE $address";
+    }
+    if (@orwhere) {
+      push @where, "EXISTS(
+        SELECT 1 FROM cust_location 
+        WHERE cust_location.custnum = cust_main.custnum
+          AND (".join(' OR ',@orwhere).")
+        )";
+    }
   }
 
   ##
@@ -631,7 +678,9 @@ sub search {
   # parse with hardcoded tax location checkbox
   ##
 
-  push @where, "ship_location.geocode is not null"
+  my $tax_prefix = FS::Conf->new->exists('tax-ship_location') ? 'ship_' 
+                                                              : 'bill_';
+  push @where, "${tax_prefix}location.geocode is not null"
     if $params->{'with_geocode'};
 
   ##