X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcontact.pm;h=c1b558d6c01732ec0977483baefe9d3034299d5c;hb=6fd39bf8dfa989aaedea59e5e3cd609642f9e024;hp=589fc7c19f2e145db8c549f97d23c75289444438;hpb=aeb90ade381fc3d5477db0334048c2af623fccfe;p=freeside.git diff --git a/FS/FS/contact.pm b/FS/FS/contact.pm index 589fc7c19..c1b558d6c 100644 --- a/FS/FS/contact.pm +++ b/FS/FS/contact.pm @@ -1,11 +1,13 @@ package FS::contact; -use base qw( FS::Record ); +use base qw( FS::Password_Mixin + FS::Record ); use strict; use vars qw( $skip_fuzzyfiles ); use Carp; use Scalar::Util qw( blessed ); use FS::Record qw( qsearch qsearchs dbh ); +use FS::Cursor; use FS::contact_phone; use FS::contact_email; use FS::queue; @@ -88,7 +90,6 @@ empty or bcrypt disabled - =back =head1 METHODS @@ -111,6 +112,26 @@ 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. + +Then, if the object has any fields named C an +L record will be created for each of them. Those fields +should contain phone numbers of the appropriate types (where N is the key of +an L record identifying the type of number: daytime, night, +etc.). + +After inserting the record, if the object has a 'custnum' or 'prospectnum' +field, an L or L record will be +created to link the contact to the customer. The following fields will also +be included in that record, if they are set on the object: +- classnum +- comment +- selfservice_access +- invoice_dest + =cut sub insert { @@ -133,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->$_(''); } @@ -164,20 +185,24 @@ 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 = ''; @@ -259,7 +284,10 @@ sub insert { } if ( $link_hash{'selfservice_access'} eq 'R' - or ( $link_hash{'selfservice_access'} && $cust_contact ) + or ( $link_hash{'selfservice_access'} + && $cust_contact + && ! length($self->_password) + ) ) { my $error = $self->send_reset_email( queue=>1 ); @@ -350,7 +378,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; @@ -394,12 +423,15 @@ 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; @@ -452,8 +484,11 @@ sub replace { ); my $contact_phone = qsearchs('contact_phone', \%cp); + my $pv = $self->get($pf); + $pv =~ s/\s//g; + #if new value is empty, delete old entry - if (!$self->get($pf)) { + if (!$pv) { if ($contact_phone) { $error = $contact_phone->delete; if ( $error ) { @@ -466,7 +501,7 @@ sub replace { $contact_phone ||= new FS::contact_phone \%cp; - my %cpd = _parse_phonestring( $self->get($pf) ); + my %cpd = _parse_phonestring( $pv ); $contact_phone->set( $_ => $cpd{$_} ) foreach keys %cpd; my $method = $contact_phone->contactphonenum ? 'replace' : 'insert'; @@ -760,9 +795,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; @@ -831,6 +879,7 @@ sub send_reset_email { #die "selfservice-password_reset_msgnum unset" unless $msgnum; return { 'error' => "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; my %msg_template = ( 'to' => join(',', map $_->emailaddress, @contact_email ), 'cust_main' => $cust_main, @@ -840,11 +889,14 @@ sub send_reset_email { if ( $opt{'queue'} ) { #or should queueing just be the default? + my $cust_msg = $msg_template->prepare( %msg_template ); + my $error = $cust_msg->insert; + return { 'error' => $error } if $error; my $queue = new FS::queue { - 'job' => 'FS::Misc::process_send_email', + 'job' => 'FS::cust_msg::process_send', 'custnum' => $cust_main ? $cust_main->custnum : '', }; - $queue->insert( $msg_template->prepare( %msg_template ) ); + $queue->insert( $cust_msg->custmsgnum ); } else { @@ -876,6 +928,7 @@ sub cgi_contact_fields { my @contact_fields = qw( classnum first last title comment emailaddress selfservice_access + invoice_dest ); push @contact_fields, 'phonetypenum'. $_->phonetypenum @@ -889,14 +942,40 @@ use FS::upgrade_journal; sub _upgrade_data { #class method my ($class, %opts) = @_; - unless ( FS::upgrade_journal->is_done('contact__DUPEMAIL') ) { + # 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', {}); + while (my $cust_main_invoice = $search->fetch) { + my $custnum = $cust_main_invoice->custnum; + my $dest = $cust_main_invoice->dest; + my $cust_main = $cust_main_invoice->cust_main; + + if ( $dest =~ /^\d+$/ ) { + my $svc_acct = FS::svc_acct->by_key($dest); + die "custnum $custnum, invoice destination svcnum $svc_acct does not exist\n" + if !$svc_acct; + $dest = $svc_acct->email; + } + + my $error = $cust_main->replace( invoicing_list => [ $dest ] ); + + if ( $error ) { + die "custnum $custnum, invoice destination $dest, creating contact: $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') ) { foreach my $contact (qsearch('contact', {})) { my $error = $contact->replace; die $error if $error; } - FS::upgrade_journal->set_done('contact__DUPEMAIL'); + FS::upgrade_journal->set_done('contact_invoice_dest'); } }