last bit of magic for RT ticket customer auto-association: look for requestor email...
[freeside.git] / FS / FS / cust_main.pm
index de4d38d..37f98c6 100644 (file)
@@ -2166,8 +2166,7 @@ sub bill {
       # only for figuring next bill date, nothing else, so, reset $sdate again
       # here
       $sdate = $cust_pkg->bill || $cust_pkg->setup || $time;
-      $cust_pkg->last_bill($sdate)
-        if $cust_pkg->dbdef_table->column('last_bill');
+      $cust_pkg->last_bill($sdate);
 
       if ( $part_pkg->freq =~ /^\d+$/ ) {
         $mon += $part_pkg->freq;
@@ -3170,7 +3169,7 @@ sub realtime_bop {
     'gatewaynum' => ( $payment_gateway ? $payment_gateway->gatewaynum : '' ),
   };
   $cust_pay_pending->payunique( $options{payunique} )
-    if length($options{payunique});
+    if defined($options{payunique}) && length($options{payunique});
   my $cpp_new_err = $cust_pay_pending->insert; #mutex lost when this is inserted
   return $cpp_new_err if $cpp_new_err;
 
@@ -3323,7 +3322,8 @@ sub realtime_bop {
        'paydate'  => $paydate,
     } );
     #doesn't hurt to know, even though the dup check is in cust_pay_pending now
-    $cust_pay->payunique( $options{payunique} ) if length($options{payunique});
+    $cust_pay->payunique( $options{payunique} )
+      if defined($options{payunique}) && length($options{payunique});
 
     my $oldAutoCommit = $FS::UID::AutoCommit;
     local $FS::UID::AutoCommit = 0;
@@ -4633,13 +4633,14 @@ the error, otherwise returns false.
 
 sub charge {
   my $self = shift;
-  my ( $amount, $pkg, $comment, $taxclass, $additional );
+  my ( $amount, $pkg, $comment, $taxclass, $additional, $classnum );
   if ( ref( $_[0] ) ) {
     $amount     = $_[0]->{amount};
     $pkg        = exists($_[0]->{pkg}) ? $_[0]->{pkg} : 'One-time charge';
     $comment    = exists($_[0]->{comment}) ? $_[0]->{comment}
                                            : '$'. sprintf("%.2f",$amount);
     $taxclass   = exists($_[0]->{taxclass}) ? $_[0]->{taxclass} : '';
+    $classnum   = exists($_[0]->{classnum}) ? $_[0]->{classnum} : '';
     $additional = $_[0]->{additional};
   }else{
     $amount     = shift;
@@ -4666,6 +4667,7 @@ sub charge {
     'plan'     => 'flat',
     'freq'     => 0,
     'disabled' => 'Y',
+    'classnum' => $classnum ? $classnum : '',
     'taxclass' => $taxclass,
   } );
 
@@ -5191,8 +5193,8 @@ sub _money_table_where {
   my @where = ();
   push @where, "cust_main.custnum = $table.custnum" unless $opt{'total'};
   if ( $table eq 'cust_bill' || $opt{'unapplied_date'} ) {
-    push @where, "$table._date <= $start" if length($start);
-    push @where, "$table._date >  $end"   if length($end);
+    push @where, "$table._date <= $start" if defined($start) && length($start);
+    push @where, "$table._date >  $end"   if defined($end)   && length($end);
   }
   push @where, @{$opt{'where'}} if $opt{'where'};
   my $where = scalar(@where) ? 'WHERE '. join(' AND ', @where ) : '';
@@ -5329,10 +5331,14 @@ sub smart_search {
 
     }
 
-  } elsif ( $search =~ /^\s*(\d+)\s*$/ ) { # customer # search
-                                           # (also try agent_custid)
-                                           # (regex needs tweaking if your
-                                           #  legacy cust numbers have letters)
+  # 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*$/
+               )
+          )
+  {
 
     push @cust_main, qsearch( {
       'table'     => 'cust_main',
@@ -5509,6 +5515,72 @@ sub smart_search {
 
 }
 
+=item email_search
+
+Accepts the following options: I<email>, the email address to search for.  The
+email address will be searched for as an email invoice destination and as an
+svc_acct account.
+
+#Any additional options are treated as an additional qualifier on the search
+#(i.e. I<agentnum>).
+
+Returns a (possibly empty) array of FS::cust_main objects (but usually just
+none or one).
+
+=cut
+
+sub email_search {
+  my %options = @_;
+
+  local($DEBUG) = 1;
+
+  my $email = delete $options{'email'};
+
+  #we're only being used by RT at the moment... no agent virtualization yet
+  #my $agentnums_sql = $FS::CurrentUser::CurrentUser->agentnums_sql;
+
+  my @cust_main = ();
+
+  if ( $email =~ /([^@]+)\@([^@]+)/ ) {
+
+    my ( $user, $domain ) = ( $1, $2 );
+
+    warn "$me smart_search: searching for $user in domain $domain"
+      if $DEBUG;
+
+    push @cust_main,
+      map $_->cust_main,
+          qsearch( {
+                     'table'     => 'cust_main_invoice',
+                     'hashref'   => { 'dest' => $email },
+                   }
+                 );
+
+    push @cust_main,
+      map  $_->cust_main,
+      grep $_,
+      map  $_->cust_svc->cust_pkg,
+          qsearch( {
+                     'table'     => 'svc_acct',
+                     'hashref'   => { 'username' => $user, },
+                     'extra_sql' =>
+                       'AND ( SELECT domain FROM svc_domain
+                                WHERE svc_acct.domsvc = svc_domain.svcnum
+                            ) = '. dbh->quote($domain),
+                   }
+                 );
+  }
+
+  my %saw = ();
+  @cust_main = grep { !$saw{$_->custnum}++ } @cust_main;
+
+  warn "$me smart_search: found ". scalar(@cust_main). " unique customers"
+    if $DEBUG;
+
+  @cust_main;
+
+}
+
 =item check_and_rebuild_fuzzyfiles
 
 =cut