use FS::part_pkg;
use FS::part_svc;
use FS::svc_acct_pop;
-use FS::cust_main_invoice;
use FS::svc_domain;
use FS::svc_pbx;
use FS::raddb;
$passwordmin = ( defined($passwordmin) && $passwordmin =~ /\d+/ )
? $passwordmin
: 6;
- $passwordmax = $conf->config('passwordmax') || 8;
+ $passwordmax = $conf->config('passwordmax') || 12;
$username_letter = $conf->exists('username-letter');
$username_letterfirst = $conf->exists('username-letterfirst');
$username_noperiod = $conf->exists('username-noperiod');
$smtpmachine = $conf->config('smtpmachine');
$radius_password = $conf->config('radius-password') || 'Password';
$radius_ip = $conf->config('radius-ip') || 'Framed-IP-Address';
- @pw_set = ( 'A'..'Z' ) if $conf->exists('password-generated-allcaps');
+ @pw_set = FS::svc_acct->pw_set;
}
);
@saltset = ( 'a'..'z' , 'A'..'Z' , '0'..'9' , '.' , '/' );
-@pw_set = ( 'a'..'z', 'A'..'Z', '0'..'9', '(', ')', '#', '.', ',' );
sub _cache {
my $self = shift;
disable_inventory => 1,
},
'_password' => { label => 'Password',
- required => 1
+ #required => 1
},
'gid' => {
label => 'GID',
|| $conf->exists('emailinvoiceauto')
&& ! $cust_main->invoicing_list_emailonly
) {
- my @invoicing_list = $cust_main->invoicing_list;
- push @invoicing_list, $self->email;
- $cust_main->invoicing_list(\@invoicing_list);
+
+ # slight false laziness w/ edit/process/cust_main.cgi...
+ # and also slightly arbitrary behavior.
+ #
+ # this will never happen but check it anyway
+ my ($contact) = map { $_->contact }
+ qsearch('contact_email', { emailaddress => $self->email });
+
+ if (!$contact) {
+ # if the "real name" of this account matches the first + last name
+ # of a contact, attach the email address to that person.
+ my @contacts = map { $_->contact } $cust_main->cust_contact;
+ my $myname = $self->get('finger');
+ my ($contact) =
+ grep { $_->get('first') . ' ' . $_->get('last') eq $myname } @contacts;
+ # otherwise just pick the first one
+ $contact = $contacts[0];
+ }
+ # if there is one
+ $contact ||= FS::contact->new({
+ 'custnum' => $cust_main->get('custnum'),
+ 'locationnum' => $cust_main->get('bill_locationnum'),
+ 'last' => $cust_main->get('last'),
+ 'first' => $cust_main->get('first'),
+ });
+ $contact->set('emailaddress', $self->email);
+ $contact->set('invoice_dest', 'Y');
+
+ if ( $contact->get('contactnum') ) {
+ $error = $contact->replace;
+ } else {
+ $error = $contact->insert;
+ }
+
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "creating invoice destination contact: $error";
+ }
}
#welcome email
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
- foreach my $cust_main_invoice (
- qsearch( 'cust_main_invoice', { 'dest' => $self->svcnum } )
+ foreach my $svc_domain (
+ qsearch( 'svc_domain', { 'catchall' => $self->svcnum } )
) {
- unless ( defined($cust_main_invoice) ) {
- warn "WARNING: something's wrong with qsearch";
- next;
- }
- my %hash = $cust_main_invoice->hash;
- $hash{'dest'} = $self->email;
- my $new = new FS::cust_main_invoice \%hash;
- my $error = $new->replace($cust_main_invoice);
+ my %hash = new FS::svc_domain->hash;
+ $hash{'catchall'} = '';
+ my $new = new FS::svc_domain \%hash;
+ my $error = $new->replace($svc_domain);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
}
}
- foreach my $svc_domain (
- qsearch( 'svc_domain', { 'catchall' => $self->svcnum } )
+ foreach my $svc_phone (
+ qsearch( 'svc_phone', { 'forward_svcnum' => $self->svcnum })
) {
- my %hash = new FS::svc_domain->hash;
- $hash{'catchall'} = '';
- my $new = new FS::svc_domain \%hash;
- my $error = $new->replace($svc_domain);
+ $svc_phone->set('forward_svcnum', '');
+ my $error = $svc_phone->replace;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
}
}
- my $error = $self->SUPER::delete; # usergroup here
+ my $error = $self->delete_password_history
+ || $self->SUPER::delete; # usergroup here
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
Returns a paged search (L<FS::PagedSearch>) for Call Detail Records
associated with this service. For svc_acct, "associated with" means that
-either the "src" or the "charged_party" field of the CDR matches the
-"username" field of the service.
+either the "src" or the "charged_party" field of the CDR matches either
+the "username" field of the service or the username@domain label.
=cut
my @where;
my $did = dbh->quote($self->username);
+ my $diddomain = dbh->quote($self->label);
my $prefix = $options{'default_prefix'} || ''; #convergent.au '+61'
my $prefixdid = dbh->quote($prefix . $self->username);
if (!$options{'disable_charged_party'}) {
push @orwhere,
"charged_party = $did",
- "charged_party = $prefixdid";
+ "charged_party = $prefixdid",
+ "charged_party = $diddomain"
+ ;
}
if (!$options{'disable_src'}) {
push @orwhere,
"src = $did AND charged_party IS NULL",
- "src = $prefixdid AND charged_party IS NULL";
+ "src = $prefixdid AND charged_party IS NULL",
+ "src = $diddomain AND charged_party IS NULL"
+ ;
}
push @where, '(' . join(' OR ', @orwhere) . ')';
$self->domain. '/maildirs/'. $self->username. '/';
}
+=item password_svc_check
+
+Override, for L<FS::Password_Mixin>. Not really intended for other use.
+
+=cut
+
+sub password_svc_check {
+ my ($self, $password) = @_;
+ foreach my $field ( qw(username finger) ) {
+ foreach my $word (split(/\W+/,$self->get($field))) {
+ next unless length($word) > 2;
+ if ($password =~ /$word/i) {
+ return qq(Password contains account information '$word');
+ }
+ }
+ }
+ return '';
+}
+
=back
=head1 CLASS METHODS