allow sending email to specific contact classes, #33316
[freeside.git] / FS / FS / cust_main.pm
index 5f77ab5..4ec5a02 100644 (file)
@@ -98,12 +98,15 @@ our @encrypted_fields = ('payinfo', 'paycvv');
 sub nohistory_fields { ('payinfo', 'paycvv'); }
 
 our $conf;
+our $default_agent_custid;
+our $custnum_display_length;
 #ask FS::UID to run this stuff for us later
 #$FS::UID::callback{'FS::cust_main'} = sub { 
 install_callback FS::UID sub { 
   $conf = new FS::Conf;
-  #yes, need it for stuff below (prolly should be cached)
-  $ignore_invalid_card = $conf->exists('allow_invalid_cards');
+  $ignore_invalid_card    = $conf->exists('allow_invalid_cards');
+  $default_agent_custid   = $conf->exists('cust_main-default_agent_custid');
+  $custnum_display_length = $conf->config('cust_main-custnum-display_length');
 };
 
 sub _cache {
@@ -2874,6 +2877,73 @@ sub invoicing_list_emailonly_scalar {
   join(', ', $self->invoicing_list_emailonly);
 }
 
+=item contact_list [ CLASSNUM, ... ]
+
+Returns a list of contacts (L<FS::contact> objects) for the customer. If
+a list of contact classnums is given, returns only contacts in those
+classes. If the pseudo-classnum 'invoice' is given, returns contacts that
+are marked as invoice destinations. If '0' is given, also returns contacts
+with no class.
+
+If no arguments are given, returns all contacts for the customer.
+
+=cut
+
+sub contact_list {
+  my $self = shift;
+  my $search = {
+    table       => 'contact',
+    select      => 'contact.*, cust_contact.invoice_dest',
+    addl_from   => ' JOIN cust_contact USING (contactnum)',
+    extra_sql   => ' WHERE cust_contact.custnum = '.$self->custnum,
+  };
+
+  my @orwhere;
+  my @classnums;
+  foreach (@_) {
+    if ( $_ eq 'invoice' ) {
+      push @orwhere, 'cust_contact.invoice_dest = \'Y\'';
+    } elsif ( $_ eq '0' ) {
+      push @orwhere, 'cust_contact.classnum is null';
+    } elsif ( /^\d+$/ ) {
+      push @classnums, $_;
+    } else {
+      die "bad classnum argument '$_'";
+    }
+  }
+
+  if (@classnums) {
+    push @orwhere, 'cust_contact.classnum IN ('.join(',', @classnums).')';
+  }
+  if (@orwhere) {
+    $search->{extra_sql} .= ' AND (' .
+                            join(' OR ', map "( $_ )", @orwhere) .
+                            ')';
+  }
+
+  qsearch($search);
+}
+
+=item contact_list_email [ CLASSNUM, ... ]
+
+Same as L</contact_list>, but returns email destinations instead of contact
+objects.
+
+=cut
+
+sub contact_list_email {
+  my $self = shift;
+  my @contacts = $self->contact_list(@_);
+  my @emails;
+  foreach my $contact (@contacts) {
+    foreach my $contact_email ($contact->contact_email) {
+      push @emails,
+        $contact->firstlast . ' <' . $contact_email->emailaddress . '>';
+    }
+  }
+  @emails;
+}
+
 =item referral_custnum_cust_main
 
 Returns the customer who referred this customer (or the empty string, if
@@ -3584,34 +3654,16 @@ cust_main-default_agent_custid is set and it has a value, custnum otherwise.
 sub display_custnum {
   my $self = shift;
 
+  return $self->agent_custid
+    if $default_agent_custid && $self->agent_custid;
+
   my $prefix = $conf->config('cust_main-custnum-display_prefix', $self->agentnum) || '';
-  if ( my $special = $conf->config('cust_main-custnum-display_special') ) {
-    if ( $special eq 'CoStAg' ) {
-      $prefix = uc( join('',
-        $self->country,
-        ($self->state =~ /^(..)/),
-        $prefix || ($self->agent->agent =~ /^(..)/)
-      ) );
-    }
-    elsif ( $special eq 'CoStCl' ) {
-      $prefix = uc( join('',
-        $self->country,
-        ($self->state =~ /^(..)/),
-        ($self->classnum ? $self->cust_class->classname =~ /^(..)/ : '__')
-      ) );
-    }
-    # add any others here if needed
-  }
 
-  my $length = $conf->config('cust_main-custnum-display_length');
-  if ( $conf->exists('cust_main-default_agent_custid') && $self->agent_custid ){
-    return $self->agent_custid;
-  } elsif ( $prefix ) {
-    $length = 8 if !defined($length);
+  if ( $prefix ) {
     return $prefix . 
-           sprintf('%0'.$length.'d', $self->custnum)
-  } elsif ( $length ) {
-    return sprintf('%0'.$length.'d', $self->custnum);
+           sprintf('%0'.($custnum_display_length||8).'d', $self->custnum)
+  } elsif ( $custnum_display_length ) {
+    return sprintf('%0'.$custnum_display_length.'d', $self->custnum);
   } else {
     return $self->custnum;
   }
@@ -3818,13 +3870,17 @@ sub status { shift->cust_status(@_); }
 
 sub cust_status {
   my $self = shift;
+  return $self->hashref->{cust_status} if $self->hashref->{cust_status};
   for my $status ( FS::cust_main->statuses() ) {
     my $method = $status.'_sql';
     my $numnum = ( my $sql = $self->$method() ) =~ s/cust_main\.custnum/?/g;
     my $sth = dbh->prepare("SELECT $sql") or die dbh->errstr;
     $sth->execute( ($self->custnum) x $numnum )
       or die "Error executing 'SELECT $sql': ". $sth->errstr;
-    return $status if $sth->fetchrow_arrayref->[0];
+    if ( $sth->fetchrow_arrayref->[0] ) {
+      $self->hashref->{cust_status} = $status;
+      return $status;
+    }
   }
 }