summaryrefslogtreecommitdiff
path: root/FS
diff options
context:
space:
mode:
authorMark Wells <mark@freeside.biz>2016-04-30 18:07:50 -0700
committerMark Wells <mark@freeside.biz>2016-05-02 13:24:53 -0700
commit755159a8654a2eda89badd1498f8def3a472cb15 (patch)
tree05908f7215c7a7f3f9a0b4b416e668b9a80f5338 /FS
parentbd714630f4747b3f411ae53515a734e9e771c6b3 (diff)
allow sending email to specific contact classes, #33316
Conflicts: FS/FS/cust_main_Mixin.pm FS/FS/msg_template/email.pm httemplate/misc/email-customers.html
Diffstat (limited to 'FS')
-rw-r--r--FS/FS/cust_main.pm67
-rw-r--r--FS/FS/cust_main_Mixin.pm24
-rw-r--r--FS/FS/msg_template.pm22
3 files changed, 106 insertions, 7 deletions
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index cfcd5f43f..ef3ab61a7 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -3363,6 +3363,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
diff --git a/FS/FS/cust_main_Mixin.pm b/FS/FS/cust_main_Mixin.pm
index 96e520d52..94e6eaa29 100644
--- a/FS/FS/cust_main_Mixin.pm
+++ b/FS/FS/cust_main_Mixin.pm
@@ -380,6 +380,12 @@ HTML body
Text body
+=item to_contact_classnum
+
+The customer contact class (or classes, as a comma-separated list) to send
+the message to. If unspecified, will be sent to any contacts that are marked
+as invoice destinations (the equivalent of specifying 'invoice').
+
=back
Returns an error message, or false for success.
@@ -403,6 +409,7 @@ sub email_search_result {
my $subject = delete $param->{subject};
my $html_body = delete $param->{html_body};
my $text_body = delete $param->{text_body};
+ my $to_contact_classnum = delete $param->{to_contact_classnum};
my $error = '';
my $job = delete $param->{'job'}
@@ -455,10 +462,21 @@ sub email_search_result {
%message = $msg_template->prepare(
'cust_main' => $cust_main,
'object' => $obj,
+ 'to_contact_classnum' => $to_contact_classnum,
);
- }
- else {
- my @to = $cust_main->invoicing_list_emailonly;
+
+ } else {
+ # 3.x: false laziness with msg_template.pm; on 4.x, all email notices
+ # are generated from templates and this case goes away
+ my @classes;
+ if ( $opt{'to_contact_classnum'} ) {
+ my $classnum = $opt{'to_contact_classnum'};
+ @classes = ref($classnum) ? @$classnum : split(',', $classnum);
+ }
+ if (!@classes) {
+ @classes = ( 'invoice' );
+ }
+ my @to = $cust_main->contact_list_email(@classes);
next if !@to;
%message = (
diff --git a/FS/FS/msg_template.pm b/FS/FS/msg_template.pm
index 70e556924..50a9b3f27 100644
--- a/FS/FS/msg_template.pm
+++ b/FS/FS/msg_template.pm
@@ -383,12 +383,26 @@ sub prepare {
my @to;
if ( exists($opt{'to'}) ) {
+
@to = split(/\s*,\s*/, $opt{'to'});
+
+ } elsif ( $cust_main ) {
+
+ my @classes;
+ if ( $opt{'to_contact_classnum'} ) {
+ my $classnum = $opt{'to_contact_classnum'};
+ @classes = ref($classnum) ? @$classnum : split(',', $classnum);
+ }
+ if (!@classes) {
+ @classes = ( 'invoice' );
+ }
+ @to = $cust_main->contact_list_email(@classes);
+
+ } else {
+
+ die 'no To: address or cust_main object specified';
+
}
- else {
- @to = $cust_main->invoicing_list_emailonly;
- }
- # no warning when preparing with no destination
my $from_addr = $self->from_addr;