RT# 77498 - Customer Import now uses contact/Import.pm rather than contact_import.pm
[freeside.git] / FS / FS / contact.pm
index 188d287..44c5388 100644 (file)
@@ -10,6 +10,7 @@ use FS::Record qw( qsearch qsearchs dbh );
 use FS::Cursor;
 use FS::contact_phone;
 use FS::contact_email;
 use FS::Cursor;
 use FS::contact_phone;
 use FS::contact_email;
+use FS::contact::Import;
 use FS::queue;
 use FS::phone_type; #for cgi_contact_fields
 use FS::cust_contact;
 use FS::queue;
 use FS::phone_type; #for cgi_contact_fields
 use FS::cust_contact;
@@ -112,10 +113,10 @@ sub table { 'contact'; }
 Adds this record to the database.  If there is an error, returns the error,
 otherwise returns false.
 
 Adds this record to the database.  If there is an error, returns the error,
 otherwise returns false.
 
-If the object has an C<emailaddress> field, L<FS::contact_email> records will
-be created for each (comma-separated) email address in that field. If any of
-these coincide with an existing email address, this contact will be merged with
-the contact with that address.
+If the object has an C<emailaddress> field, L<FS::contact_email> records
+will be created for each (comma-separated) email address in that field. If
+any of these coincide with an existing email address, this contact will be
+merged with the contact with that address.
 
 Then, if the object has any fields named C<phonetypenumN> an
 L<FS::contact_phone> record will be created for each of them. Those fields
 
 Then, if the object has any fields named C<phonetypenumN> an
 L<FS::contact_phone> record will be created for each of them. Those fields
@@ -206,6 +207,10 @@ sub insert {
   }
 
   my $cust_contact = '';
   }
 
   my $cust_contact = '';
+  # if $self->custnum was set, then the customer-specific properties
+  # (custnum, classnum, invoice_dest, selfservice_access, comment) are in
+  # pseudo-fields, and are now in %link_hash. otherwise, ignore all those
+  # fields.
   if ( $custnum ) {
     my %hash = ( 'contactnum' => $self->contactnum,
                  'custnum'    => $custnum,
   if ( $custnum ) {
     my %hash = ( 'contactnum' => $self->contactnum,
                  'custnum'    => $custnum,
@@ -337,6 +342,8 @@ sub delete {
     }
   }
 
     }
   }
 
+  # if $self->custnum was set, then we're removing the contact from this
+  # customer.
   if ( $self->custnum ) {
     my $cust_contact = qsearchs('cust_contact', {
                          'contactnum'  => $self->contactnum,
   if ( $self->custnum ) {
     my $cust_contact = qsearchs('cust_contact', {
                          'contactnum'  => $self->contactnum,
@@ -438,6 +445,10 @@ sub replace {
   }
 
   my $cust_contact = '';
   }
 
   my $cust_contact = '';
+  # if $self->custnum was set, then the customer-specific properties
+  # (custnum, classnum, invoice_dest, selfservice_access, comment) are in
+  # pseudo-fields, and are now in %link_hash. otherwise, ignore all those
+  # fields.
   if ( $custnum ) {
     my %hash = ( 'contactnum' => $self->contactnum,
                  'custnum'    => $custnum,
   if ( $custnum ) {
     my %hash = ( 'contactnum' => $self->contactnum,
                  'custnum'    => $custnum,
@@ -567,6 +578,15 @@ sub replace {
     }
   }
 
     }
   }
 
+  if ( $self->get('password') ) {
+    my $error = $self->is_password_allowed($self->get('password'))
+          ||  $self->change_password($self->get('password'));
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
 
   '';
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
 
   '';
@@ -653,7 +673,7 @@ and replace methods.
 sub check {
   my $self = shift;
 
 sub check {
   my $self = shift;
 
-  if ( $self->selfservice_access eq 'R' ) {
+  if ( $self->selfservice_access eq 'R' || $self->selfservice_access eq 'P' ) {
     $self->selfservice_access('Y');
     $self->_resend('Y');
   }
     $self->selfservice_access('Y');
     $self->_resend('Y');
   }
@@ -743,9 +763,9 @@ sub firstlast {
 
 =item by_selfservice_email EMAILADDRESS
 
 
 =item by_selfservice_email EMAILADDRESS
 
-Alternate search constructor (class method).  Given an email address,
-returns the contact for that address, or the empty string if no contact
-has that email address.
+Alternate search constructor (class method).  Given an email address, returns
+the contact for that address. If that contact doesn't have selfservice access,
+or there isn't one, returns the empty string.
 
 =cut
 
 
 =cut
 
@@ -756,7 +776,13 @@ sub by_selfservice_email {
     'table'     => 'contact_email',
     'addl_from' => ' LEFT JOIN contact USING ( contactnum ) ',
     'hashref'   => { 'emailaddress' => $email, },
     'table'     => 'contact_email',
     'addl_from' => ' LEFT JOIN contact USING ( contactnum ) ',
     'hashref'   => { 'emailaddress' => $email, },
-    'extra_sql' => " AND ( disabled IS NULL OR disabled = '' )",
+    'extra_sql' => "
+      AND ( contact.disabled IS NULL )
+      AND EXISTS ( SELECT 1 FROM cust_contact
+                     WHERE contact.contactnum = cust_contact.contactnum
+                       AND cust_contact.selfservice_access = 'Y'
+                 )
+    ",
   }) or return '';
 
   $contact_email->contact;
   }) or return '';
 
   $contact_email->contact;
@@ -856,7 +882,10 @@ sub send_reset_email {
     'svcnum'     => $opt{'svcnum'},
   };
 
     'svcnum'     => $opt{'svcnum'},
   };
 
-  my $timeout = '24 hours'; #?
+  
+  my $conf = new FS::Conf;
+  my $timeout =
+    ($conf->config('selfservice-password_reset_hours') || 24 ). ' hours';
 
   my $reset_session_id;
   do {
 
   my $reset_session_id;
   do {
@@ -868,8 +897,6 @@ sub send_reset_email {
 
   #email it
 
 
   #email it
 
-  my $conf = new FS::Conf;
-
   my $cust_main = '';
   my @cust_contact = grep $_->selfservice_access, $self->cust_contact;
   $cust_main = $cust_contact[0]->cust_main if scalar(@cust_contact) == 1;
   my $cust_main = '';
   my @cust_contact = grep $_->selfservice_access, $self->cust_contact;
   $cust_main = $cust_contact[0]->cust_main if scalar(@cust_contact) == 1;
@@ -877,9 +904,9 @@ sub send_reset_email {
   my $agentnum = $cust_main ? $cust_main->agentnum : '';
   my $msgnum = $conf->config('selfservice-password_reset_msgnum', $agentnum);
   #die "selfservice-password_reset_msgnum unset" unless $msgnum;
   my $agentnum = $cust_main ? $cust_main->agentnum : '';
   my $msgnum = $conf->config('selfservice-password_reset_msgnum', $agentnum);
   #die "selfservice-password_reset_msgnum unset" unless $msgnum;
-  return { 'error' => "selfservice-password_reset_msgnum unset" } unless $msgnum;
+  return "selfservice-password_reset_msgnum unset" unless $msgnum;
   my $msg_template = qsearchs('msg_template', { msgnum => $msgnum } );
   my $msg_template = qsearchs('msg_template', { msgnum => $msgnum } );
-  return { 'error' => "selfservice-password_reset_msgnum cannot be loaded" } unless $msg_template;
+  return "selfservice-password_reset_msgnum cannot be loaded" unless $msg_template;
   my %msg_template = (
     'to'            => join(',', map $_->emailaddress, @contact_email ),
     'cust_main'     => $cust_main,
   my %msg_template = (
     'to'            => join(',', map $_->emailaddress, @contact_email ),
     'cust_main'     => $cust_main,
@@ -891,7 +918,7 @@ sub send_reset_email {
 
     my $cust_msg = $msg_template->prepare( %msg_template );
     my $error = $cust_msg->insert;
 
     my $cust_msg = $msg_template->prepare( %msg_template );
     my $error = $cust_msg->insert;
-    return { 'error' => $error } if $error;
+    return $error if $error;
     my $queue = new FS::queue {
       'job'     => 'FS::cust_msg::process_send',
       'custnum' => $cust_main ? $cust_main->custnum : '',
     my $queue = new FS::queue {
       'job'     => 'FS::cust_msg::process_send',
       'custnum' => $cust_main ? $cust_main->custnum : '',
@@ -928,7 +955,7 @@ sub cgi_contact_fields {
 
   my @contact_fields = qw(
     classnum first last title comment emailaddress selfservice_access
 
   my @contact_fields = qw(
     classnum first last title comment emailaddress selfservice_access
-    invoice_dest
+    invoice_dest password
   );
 
   push @contact_fields, 'phonetypenum'. $_->phonetypenum
   );
 
   push @contact_fields, 'phonetypenum'. $_->phonetypenum
@@ -942,9 +969,24 @@ use FS::upgrade_journal;
 sub _upgrade_data { #class method
   my ($class, %opts) = @_;
 
 sub _upgrade_data { #class method
   my ($class, %opts) = @_;
 
+  # before anything else, migrate contact.custnum to cust_contact records
+  unless ( FS::upgrade_journal->is_done('contact_invoice_dest') ) {
+
+    local($skip_fuzzyfiles) = 1;
+
+    foreach my $contact (qsearch('contact', {})) {
+      my $error = $contact->replace;
+      die $error if $error;
+    }
+
+    FS::upgrade_journal->set_done('contact_invoice_dest');
+  }
+
+
   # always migrate cust_main_invoice records over
   local $FS::cust_main::import = 1; # override require_phone and such
   my $search = FS::Cursor->new('cust_main_invoice', {});
   # always migrate cust_main_invoice records over
   local $FS::cust_main::import = 1; # override require_phone and such
   my $search = FS::Cursor->new('cust_main_invoice', {});
+  my %custnum_dest;
   while (my $cust_main_invoice = $search->fetch) {
     my $custnum = $cust_main_invoice->custnum;
     my $dest = $cust_main_invoice->dest;
   while (my $cust_main_invoice = $search->fetch) {
     my $custnum = $cust_main_invoice->custnum;
     my $dest = $cust_main_invoice->dest;
@@ -956,28 +998,21 @@ sub _upgrade_data { #class method
         if !$svc_acct;
       $dest = $svc_acct->email;
     }
         if !$svc_acct;
       $dest = $svc_acct->email;
     }
+    push @{ $custnum_dest{$custnum} ||= [] }, $dest;
 
 
-    my $error = $cust_main->replace( invoicing_list => [ $dest ] );
-
+    my $error = $cust_main_invoice->delete;
     if ( $error ) {
     if ( $error ) {
-      die "custnum $custnum, invoice destination $dest, creating contact: $error\n";
+      die "custnum $custnum, cleaning up cust_main_invoice: $error\n";
     }
     }
+  }
 
 
-    $error = $cust_main_invoice->delete;
-    die "custnum $custnum, cleaning up cust_main_invoice: $error\n" if $error;
-
-  } # while $search->fetch
-
-  unless ( FS::upgrade_journal->is_done('contact_invoice_dest') ) {
-
-    local($skip_fuzzyfiles) = 1;
-
-    foreach my $contact (qsearch('contact', {})) {
-      my $error = $contact->replace;
-      die $error if $error;
+  foreach my $custnum (keys %custnum_dest) {
+    my $dests = $custnum_dest{$custnum};
+    my $cust_main = FS::cust_main->by_key($custnum);
+    my $error = $cust_main->replace( invoicing_list => $dests );
+    if ( $error ) {
+      die "custnum $custnum, creating contact: $error\n";
     }
     }
-
-    FS::upgrade_journal->set_done('contact_invoice_dest');
   }
 
 }
   }
 
 }