RT# 73964 - Added biling event action to send an email to phone nunber, and updated...
authorChristopher Burger <burgerc@freeside.biz>
Wed, 16 Aug 2017 14:55:56 +0000 (10:55 -0400)
committerChristopher Burger <burgerc@freeside.biz>
Wed, 20 Jun 2018 14:09:31 +0000 (10:09 -0400)
Conflicts:
FS/FS/cust_main_Mixin.pm
httemplate/config/config-view.cgi
httemplate/misc/email-customers.html

FS/FS/Conf.pm
FS/FS/cust_main_Mixin.pm
FS/FS/part_event/Action/notice_to_emailtovoice.pm [new file with mode: 0644]
httemplate/config/config-view.cgi
httemplate/elements/select-cust_phone.html [new file with mode: 0644]
httemplate/elements/select.html
httemplate/elements/tr-select-cust_phone.html [new file with mode: 0644]
httemplate/misc/email-customers.html

index c21d692..31a5ec8 100644 (file)
@@ -1012,6 +1012,14 @@ my $validate_email = sub { $_[0] =~
   },
 
   {
+    'key'         => 'send-to-domain',
+    'section'     => 'email_to_voice_services',
+    'description' => 'The Domain to send email to voice to',
+    'type'        => 'text',
+    'per_agent'   => 1,
+  },
+
+  {
     'key'         => 'next-bill-ignore-time',
     'section'     => 'billing',
     'description' => 'Ignore the time portion of next bill dates when billing, matching anything from 00:00:00 to 23:59:59 on the billing day.',
index 28d894b..acce28c 100644 (file)
@@ -405,14 +405,21 @@ use Digest::SHA qw(sha1); # for duplicate checking
 sub email_search_result {
   my($class, $param) = @_;
 
+  my $conf = FS::Conf->new;
+  my $send_to_domain = $conf->config('send-to-domain');
+
   my $msgnum = $param->{msgnum};
   my $from = delete $param->{from};
   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 $emailtovoice_name = delete $param->{emailtovoice_contact};
+
   my $error = '';
 
+  my $to = $emailtovoice_name . '@' . $send_to_domain unless !$emailtovoice_name;
+
   my $job = delete $param->{'job'}
     or die "email_search_result must run from the job queue.\n";
   
@@ -458,12 +465,16 @@ sub email_search_result {
       next; # unlinked object; nothing else we can do
     }
 
+    my %to = {};
+    if ($to) { $to{'to'} = $to; }
+
     if ( $msg_template ) {
       # Now supports other context objects.
       %message = $msg_template->prepare(
         'cust_main' => $cust_main,
         'object'    => $obj,
         'to_contact_classnum' => $to_contact_classnum,
+        %to
       );
 
     } else {
@@ -490,7 +501,7 @@ sub email_search_result {
     } #if $msg_template
 
     # For non-cust_main searches, we avoid duplicates based on message
-    # body text.  
+    # body text.
     my $unique = $cust_main->custnum;
     $unique .= sha1($message{'text_body'}) if $class ne 'FS::cust_main';
     if( $sent_to{$unique} ) {
diff --git a/FS/FS/part_event/Action/notice_to_emailtovoice.pm b/FS/FS/part_event/Action/notice_to_emailtovoice.pm
new file mode 100644 (file)
index 0000000..ae766e8
--- /dev/null
@@ -0,0 +1,84 @@
+package FS::part_event::Action::notice_to_emailtovoice;
+
+use strict;
+use base qw( FS::part_event::Action );
+use FS::Record qw( qsearchs );
+use FS::msg_template;
+use FS::Conf;
+
+sub description { 'Email a email to voice notice'; }
+
+sub eventtable_hashref {
+    {
+      'cust_main'      => 1,
+      'cust_bill'      => 1,
+      'cust_pkg'       => 1,
+      'cust_pay'       => 1,
+      'cust_pay_batch' => 1,
+      'cust_statement' => 1,
+      'svc_acct'       => 1,
+    };
+}
+
+sub option_fields {
+
+  #my $conf = new FS::Conf;
+  #my $to_domain = $conf->config('send-to-domain');
+
+(
+    'to_name'   => { 'label'            => 'Address To',
+                     'type'             => 'select',
+                     'options'          => [ 'mobile', 'fax', 'daytime' ],
+                     'option_labels'    => { 'mobile'  => 'Mobile Phone #',
+                                             'fax'     => 'Fax #',
+                                             'daytime' => 'Day Time #',
+                                           },
+                     'post_field_label' => "@" , #. $to_domain ,
+                   },
+
+    'msgnum'    => { 'label'    => 'Template',
+                     'type'     => 'select-table',
+                     'table'    => 'msg_template',
+                     'name_col' => 'msgname',
+                     'hashref'  => { disabled => '' },
+                     'disable_empty' => 1,
+                },
+  );
+
+}
+
+sub default_weight { 56; } #?
+
+sub do_action {
+  my( $self, $object ) = @_;
+
+  my $conf = new FS::Conf;
+  my $to_domain = $conf->config('send-to-domain')
+    or die "Can't send notice with out send-to-domain, being set in global config \n";
+
+  my $cust_main = $self->cust_main($object);
+
+  my $msgnum = $self->option('msgnum');
+  my $name = $self->option('to_name');
+
+  my $msg_template = qsearchs('msg_template', { 'msgnum' => $msgnum } )
+      or die "Template $msgnum not found";
+
+  my $to_name = $cust_main->$name
+    or die "Can't send notice with out " . $cust_main->$name . " number set";
+
+  ## remove - from phone number
+  $to_name =~ s/-//g;
+
+  #my $to = $to_name . '@' . $self->option('to_domain');
+  my $to = $to_name . '@' . $to_domain;
+  
+  $msg_template->send(
+    'to'        => $to,
+    'cust_main' => $cust_main,
+    'object'    => $object,
+  );
+
+}
+
+1;
index 7b2e55a..7a61911 100644 (file)
@@ -420,8 +420,9 @@ my @deleteable = qw( invoice_latexreturnaddress invoice_htmlreturnaddress );
 my %deleteable = map { $_ => 1 } @deleteable;
 
 my @sections = (qw(
-    required billing invoicing notification UI API self-service ticketing
-    network_monitoring username password session shell BIND telephony
+    required billing invoicing notification email_to_voice_services UI 
+    API self-service ticketing network_monitoring username password 
+    session shell BIND telephony
   ), '', 'deprecated'
 );
 
diff --git a/httemplate/elements/select-cust_phone.html b/httemplate/elements/select-cust_phone.html
new file mode 100644 (file)
index 0000000..94cd413
--- /dev/null
@@ -0,0 +1,31 @@
+<SELECT NAME="<% $opt{'field_name'} %>" ID="<% $opt{'field_name'} %>">
+
+     <OPTION VALUE="" selected="selected">Select a phone number
+
+% foreach $p (@$phone_types) {
+       <OPTION VALUE="<% $phones_formatted{$p} %>"><% $p |h%> (<% $cust_phones->$p |h %>)              
+%}
+
+</SELECT>
+
+<%init>
+
+my %opt = @_;
+my $cust_num     = $opt{'cust_num'};
+my $phone_types  = $opt{'phone_types'};
+my $format       = $opt{'format'};
+
+my $cust_phones = qsearchs('cust_main', { 'custnum' => $cust_num })
+  or die 'unknown custnum' . $cust_num;
+
+my %phones_formatted = map {
+       $_ => format_phone_number($cust_phones->$_, $format)
+} @$phone_types;
+
+sub format_phone_number {
+       my ($n, $f) = @_;
+       if ($f eq 'xxxxxxxxxx') { $n =~ s/-//g; }       
+       return $n;
+}
+
+</%init>
\ No newline at end of file
index 59010c1..9dd4aec 100644 (file)
@@ -41,7 +41,7 @@
 %
 % }
 
-</SELECT>
+</SELECT> <% $opt{'post_field_label'} %>
 
 % }
 <%init>
diff --git a/httemplate/elements/tr-select-cust_phone.html b/httemplate/elements/tr-select-cust_phone.html
new file mode 100644 (file)
index 0000000..cf88392
--- /dev/null
@@ -0,0 +1,12 @@
+  <TR>
+    <TD ALIGN="right"><% $opt{'label'} || 'Customer Phones' %></TD>
+    <TD>
+      <% include( '/elements/select-cust_phone.html', %opt ) %>
+    </TD>
+  </TR>
+
+<%init>
+
+my %opt = @_;
+
+</%init>
index b8ba997..6e37d74 100644 (file)
@@ -46,6 +46,8 @@ should be used to set msgnum or from/subject/html_body cgi params
 <INPUT TYPE="hidden" NAME="search" VALUE="<% encode_base64(nfreeze(\%search)) %>">
 <INPUT TYPE="hidden" NAME="popup" VALUE="<% $popup %>">
 <INPUT TYPE="hidden" NAME="url" VALUE="<% $url | h %>">
+<INPUT TYPE="hidden" NAME="emailtovoice_contact" VALUE="<% scalar($cgi->param('emailtovoice_contact')) |h %>">
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% scalar($cgi->param('custnum')) |h %>">
 
 % if ( $cgi->param('action') eq 'send' ) { 
 
@@ -55,13 +57,12 @@ should be used to set msgnum or from/subject/html_body cgi params
     <& /elements/progress-init.html,
                  'OneTrueForm',
                  [ qw( search table from subject html_body text_body
-                        msgnum to_contact_classnum ) ],
+                        msgnum to_contact_classnum emailtovoice_contact custnum ) ],
                  $process_url,
                  $pdest,
     &>
 
 % } elsif ( $cgi->param('action') eq 'preview' ) {
-
     <INPUT TYPE="hidden" NAME="to_contact_classnum" VALUE="<% join(',', @contact_classnum) %>">
     <FONT SIZE="+2">Preview notice</FONT>
 
@@ -151,7 +152,11 @@ Template:
     &>
     <BR>
 % # select destination contact classes
-Send to contacts:
+<TABLE CELLSPACING=0 id="send_to_contacts_table">
+<TR>
+ <TD>Send to contacts:</TD>
+ <TD>
+   <div id="contactclassesdiv">
   <& /elements/checkboxes.html,
     'style'               => 'display: inline; vertical-align: top',
     'disable_links'       => 1,
@@ -162,6 +167,24 @@ Send to contacts:
       $name eq 'invoice' #others default to unchecked
     },
   &>
+   </div>
+% if ($send_to_domain) {
+   <div>
+     <INPUT TYPE="checkbox" NAME="emailtovoice"  ID="emailtovoice" VALUE="ON" onclick="toggleDiv(this)">Email to voice
+   </div>
+   <div id="emailtovoicediv" style="display:none";>
+
+      <& /elements/select-cust_phone.html,
+               'cust_num'     => $cgi->param('custnum'),
+               'field_name'   => 'emailtovoice_contact',
+               'format'       => 'xxxxxxxxxx',
+               'phone_types'  => [ 'daytime', 'night', 'fax', 'mobile' ],
+      &>@<% $send_to_domain |h %>
+   </div>
+% }
+ </TD>
+</TR>
+</TABLE>
 <BR>
 % # if sending a one-off message, show a form to edit it
   <TABLE BGCOLOR="#cccccc" CELLSPACING=0 WIDTH="100%" id="table_no_template">
@@ -199,6 +222,7 @@ Send to contacts:
 %#Substitution vars:
 
     <INPUT TYPE="hidden" NAME="action" VALUE="preview">
+    <INPUT TYPE="hidden" NAME="custnum" VALUE="<% scalar($cgi->param('custnum')) |h %>">
     <INPUT TYPE="submit" VALUE="Preview notice">
 
 % } #end not action or alternate form
@@ -211,6 +235,18 @@ Send to contacts:
     </SCRIPT>
 % }
 
+<SCRIPT TYPE="text/javascript">
+function toggleDiv(obj) {
+  var box_contactclasses = document.getElementById('contactclassesdiv');
+  var box_emailtovoice = document.getElementById('emailtovoicediv');
+
+  box_emailtovoice.style.display = (box_emailtovoice.style.display == 'none') ? 'block' : 'none';
+  document.getElementById('emailtovoice_contact').options[0].selected=true;
+
+  box_contactclasses.style.display = (box_contactclasses.style.display == 'none') ? 'block' : 'none';
+}
+</SCRIPT>
+
 <& /elements/footer.html &>
 
 <%init>
@@ -219,12 +255,16 @@ my %opt = @_;
 
 $opt{'acl'} ||= 'Bulk send customer notices';
 
+my $email_to;
+
 die "access denied"
   unless $FS::CurrentUser::CurrentUser->access_right($opt{'acl'});
 
 my $conf = FS::Conf->new;
 my @no_search_fields = qw( action table from subject html_body text_body popup url );
 
+my $send_to_domain = $conf->config('send-to-domain');
+
 my $form_action = $opt{'form_action'} || 'email-customers.html';
 my $process_url = $opt{'process_url'} || 'process/email-customers.html';
 my $title = $opt{'title'} || 'Send customer notices';
@@ -310,6 +350,11 @@ if ( $cgi->param('action') eq 'preview' ) {
 
   # contact_class_X params in preview
   foreach my $param ( $cgi->param ) {
+    if ($cgi->param('emailtovoice_contact')) {
+      $email_to = $cgi->param('emailtovoice_contact') . '@' . $send_to_domain;
+      push @contact_classnum, 'emailtovoice';
+      push @contact_classname, $email_to;
+    }
     if ( $param =~ /^contact_class_(\w+)$/ ) {
       push @contact_classnum, $1;
       if ( $1 eq 'invoice' ) {
@@ -327,10 +372,12 @@ if ( $cgi->param('action') eq 'preview' ) {
 my @contact_checkboxes = (
   [ 'invoice' => { label => 'Invoice recipients' } ]
 );
+
 foreach my $class (qsearch('contact_class', { disabled => '' })) {
   push @contact_checkboxes, [
     $class->classnum,
     { label => $class->classname }
   ];
 }
+
 </%init>