X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2Fcontact.pm;h=fd3e9d770dd8a4ac171fdf5784d7f5062b27f091;hp=0428d898b830d6ec5adffcc75e640d7df207f5aa;hb=389b6f1116c3309c2ee57a6c295ed1a793503095;hpb=b2fd002f3285b70311642f8ff0025598d42bd16e diff --git a/FS/FS/contact.pm b/FS/FS/contact.pm index 0428d898b..fd3e9d770 100644 --- a/FS/FS/contact.pm +++ b/FS/FS/contact.pm @@ -1,5 +1,6 @@ package FS::contact; -use base qw( FS::Record ); +use base qw( FS::Password_Mixin + FS::Record ); use strict; use vars qw( $skip_fuzzyfiles ); @@ -89,10 +90,6 @@ empty or bcrypt disabled -=item invoice_dest - -empty, or 'Y' if email invoices should be sent to this contact - =back =head1 METHODS @@ -115,10 +112,10 @@ sub table { 'contact'; } Adds this record to the database. If there is an error, returns the error, otherwise returns false. -If the object has an C field, L 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 field, L 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 an L record will be created for each of them. Those fields @@ -133,6 +130,7 @@ be included in that record, if they are set on the object: - classnum - comment - selfservice_access +- invoice_dest =cut @@ -156,7 +154,7 @@ sub insert { $self->custnum(''); my %link_hash = (); - for (qw( classnum comment selfservice_access )) { + for (qw( classnum comment selfservice_access invoice_dest )) { $link_hash{$_} = $self->get($_); $self->$_(''); } @@ -187,23 +185,31 @@ sub insert { } + my $error; if ( $existing_contact ) { $self->$_($existing_contact->$_()) for qw( contactnum _password _password_encoding ); - $self->SUPER::replace($existing_contact); + $error = $self->SUPER::replace($existing_contact); } else { - my $error = $self->SUPER::insert; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; - } + $error = $self->SUPER::insert; + + } + $error ||= $self->insert_password_history; + + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; } 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, @@ -335,6 +341,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, @@ -376,7 +384,8 @@ sub delete { } } - my $error = $self->SUPER::delete; + my $error = $self->delete_password_history + || $self->SUPER::delete; if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error; @@ -420,18 +429,25 @@ sub replace { $self->custnum(''); my %link_hash = (); - for (qw( classnum comment selfservice_access )) { + for (qw( classnum comment selfservice_access invoice_dest )) { $link_hash{$_} = $self->get($_); $self->$_(''); } my $error = $self->SUPER::replace($old); + if ( $old->_password ne $self->_password ) { + $error ||= $self->insert_password_history; + } if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error; } 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, @@ -666,7 +682,6 @@ sub check { || $self->ut_textn('_password') || $self->ut_enum('_password_encoding', [ '', 'bcrypt']) || $self->ut_enum('disabled', [ '', 'Y' ]) - || $self->ut_flag('invoice_dest') ; return $error if $error; @@ -738,9 +753,9 @@ sub firstlast { =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 @@ -751,7 +766,8 @@ sub by_selfservice_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 ( contact.selfservice_access = 'Y' )", }) or return ''; $contact_email->contact; @@ -790,9 +806,22 @@ sub authenticate_password { } +=item change_password NEW_PASSWORD + +Changes the contact's selfservice access password to NEW_PASSWORD. This does +not check password policy rules (see C) and will return +an error only if editing the record fails for some reason. + +If NEW_PASSWORD is the same as the existing password, this does nothing. + +=cut + sub change_password { my($self, $new_password) = @_; + # do nothing if the password is unchanged + return if $self->authenticate_password($new_password); + $self->change_password_fields( $new_password ); $self->replace; @@ -859,9 +888,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; - 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 } ); - 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, @@ -873,7 +902,7 @@ sub send_reset_email { 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 : '', @@ -924,9 +953,24 @@ use FS::upgrade_journal; 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', {}); + my %custnum_dest; while (my $cust_main_invoice = $search->fetch) { my $custnum = $cust_main_invoice->custnum; my $dest = $cust_main_invoice->dest; @@ -938,26 +982,21 @@ sub _upgrade_data { #class method if !$svc_acct; $dest = $svc_acct->email; } + push @{ $custnum_dest{$custnum} ||= [] }, $dest; - my $error = $cust_main->replace( [ $dest ] ); - + my $error = $cust_main_invoice->delete; 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__DUPEMAIL') ) { - - 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__DUPEMAIL'); } }