[freeside-commits] freeside/FS/FS ConfDefaults.pm, 1.2.2.3, 1.2.2.4 Misc.pm, 1.19.2.8, 1.19.2.9 cust_main.pm, 1.271.2.47, 1.271.2.48

Ivan,,, ivan at wavetail.420.am
Mon Jun 16 20:36:08 PDT 2008


Update of /home/cvs/cvsroot/freeside/FS/FS
In directory wavetail.420.am:/tmp/cvs-serv32538/FS/FS

Modified Files:
      Tag: FREESIDE_1_7_BRANCH
	ConfDefaults.pm Misc.pm cust_main.pm 
Log Message:
finish adding a feature to easily list all email addresses for an agent & send them email

Index: ConfDefaults.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/ConfDefaults.pm,v
retrieving revision 1.2.2.3
retrieving revision 1.2.2.4
diff -u -d -r1.2.2.3 -r1.2.2.4
--- ConfDefaults.pm	19 Dec 2007 21:05:52 -0000	1.2.2.3
+++ ConfDefaults.pm	17 Jun 2008 03:36:03 -0000	1.2.2.4
@@ -56,6 +56,9 @@
   'Cust# | Cust. Status | Name | Company | Address 1 | Address 2 | City | State | Zip | Country | Day phone | Night phone | Fax number | Invoicing email(s) | Payment Type | Current Balance' => 
     'custnum | Status | Last, First | Company | (all address fields ) | ( all phones ) | Invoicing email(s) | Payment Type | Current Balance',
 
+  'Invoicing email(s)' => 'Invoicing email(s)',
+  'Cust# | Invoicing email(s)' => 'custnum | Invoicing email(s)',
+
 ); }
 
 =back

Index: Misc.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Misc.pm,v
retrieving revision 1.19.2.8
retrieving revision 1.19.2.9
diff -u -d -r1.19.2.8 -r1.19.2.9
--- Misc.pm	10 Jun 2008 17:39:21 -0000	1.19.2.8
+++ Misc.pm	17 Jun 2008 03:36:03 -0000	1.19.2.9
@@ -12,7 +12,7 @@
 #instead
 
 @ISA = qw( Exporter );
- at EXPORT_OK = qw( send_email send_fax
+ at EXPORT_OK = qw( generate_email send_email send_fax
                  states_hash counties state_label
                  card_types
                  generate_ps generate_pdf do_print
@@ -40,29 +40,173 @@
 
 =over 4
 
+=item generate_email OPTION => VALUE ...
+
+Options:
+
+=item from
+
+Sender address, required
+
+=item to
+
+Recipient address, required
+
+=item subject
+
+email subject, required
+
+=item html_body
+
+Email body (HTML alternative).  Arrayref of lines, or scalar.
+
+Will be placed inside an HTML <BODY> tag.
+
+=item text_body
+
+Email body (Text alternative).  Arrayref of lines, or scalar.
+
+=back
+
+Returns an argument list to be passsed to L<send_email>.
+
+=cut
+
+#false laziness w/FS::cust_bill::generate_email
+
+use MIME::Entity;
+use HTML::Entities;
+
+sub generate_email {
+  my %args = @_;
+
+  my $me = '[FS::Misc::generate_email]';
+
+  my %return = (
+    'from'    => $args{'from'},
+    'to'      => $args{'to'},
+    'subject' => $args{'subject'},
+  );
+
+  #if (ref($args{'to'}) eq 'ARRAY') {
+  #  $return{'to'} = $args{'to'};
+  #} else {
+  #  $return{'to'} = [ grep { $_ !~ /^(POST|FAX)$/ }
+  #                         $self->cust_main->invoicing_list
+  #                  ];
+  #}
+
+  warn "$me creating HTML/text multipart message"
+    if $DEBUG;
+
+  $return{'nobody'} = 1;
+
+  my $alternative = build MIME::Entity
+    'Type'        => 'multipart/alternative',
+    'Encoding'    => '7bit',
+    'Disposition' => 'inline'
+  ;
+
+  my $data;
+  if ( ref($args{'text_body'}) eq 'ARRAY' ) {
+    $data = $args{'text_body'};
+  } else {
+    $data = [ split(/\n/, $args{'text_body'}) ];
+  }
+
+  $alternative->attach(
+    'Type'        => 'text/plain',
+    #'Encoding'    => 'quoted-printable',
+    'Encoding'    => '7bit',
+    'Data'        => $data,
+    'Disposition' => 'inline',
+  );
+
+  my @html_data;
+  if ( ref($args{'html_body'}) eq 'ARRAY' ) {
+    @html_data = @{ $args{'html_body'} };
+  } else {
+    @html_data = split(/\n/, $args{'html_body'});
+  }
+
+  $alternative->attach(
+    'Type'        => 'text/html',
+    'Encoding'    => 'quoted-printable',
+    'Data'        => [ '<html>',
+                       '  <head>',
+                       '    <title>',
+                       '      '. encode_entities($return{'subject'}), 
+                       '    </title>',
+                       '  </head>',
+                       '  <body bgcolor="#e8e8e8">',
+                       @html_data,
+                       '  </body>',
+                       '</html>',
+                     ],
+    'Disposition' => 'inline',
+    #'Filename'    => 'invoice.pdf',
+  );
+
+  #no other attachment:
+  # multipart/related
+  #   multipart/alternative
+  #     text/plain
+  #     text/html
+
+  $return{'content-type'} = 'multipart/related';
+  $return{'mimeparts'} = [ $alternative ];
+  $return{'type'} = 'multipart/alternative'; #Content-Type of first part...
+  #$return{'disposition'} = 'inline';
+
+  %return;
+
+}
+
 =item send_email OPTION => VALUE ...
 
 Options:
 
-I<from> - (required)
+=over 4
 
-I<to> - (required) comma-separated scalar or arrayref of recipients
+=item from
 
-I<subject> - (required)
+(required)
 
-I<content-type> - (optional) MIME type for the body
+=item to
 
-I<body> - (required unless I<nobody> is true) arrayref of body text lines
+(required) comma-separated scalar or arrayref of recipients
 
-I<mimeparts> - (optional, but required if I<nobody> is true) arrayref of MIME::Entity->build PARAMHASH refs or MIME::Entity objects.  These will be passed as arguments to MIME::Entity->attach().
+=item subject
 
-I<nobody> - (optional) when set true, send_email will ignore the I<body> option and simply construct a message with the given I<mimeparts>.  In this case,
+(required)
+
+=item content-type
+
+(optional) MIME type for the body
+
+=item body
+
+(required unless I<nobody> is true) arrayref of body text lines
+
+=item mimeparts
+
+(optional, but required if I<nobody> is true) arrayref of MIME::Entity->build PARAMHASH refs or MIME::Entity objects.  These will be passed as arguments to MIME::Entity->attach().
+
+=item nobody
+
+(optional) when set true, send_email will ignore the I<body> option and simply construct a message with the given I<mimeparts>.  In this case,
 I<content-type>, if specified, overrides the default "multipart/mixed" for the outermost MIME container.
 
-I<content-encoding> - (optional) when using nobody, optional top-level MIME
+=item content-encoding
+
+(optional) when using nobody, optional top-level MIME
 encoding which, if specified, overrides the default "7bit".
 
-I<type> - (optional) type parameter for multipart/related messages
+=item type
+
+(optional) type parameter for multipart/related messages
+
+=back
 
 =cut
 

Index: cust_main.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_main.pm,v
retrieving revision 1.271.2.47
retrieving revision 1.271.2.48
diff -u -d -r1.271.2.47 -r1.271.2.48
--- cust_main.pm	5 Jun 2008 20:09:34 -0000	1.271.2.47
+++ cust_main.pm	17 Jun 2008 03:36:03 -0000	1.271.2.48
@@ -24,7 +24,7 @@
 use Data::Dumper;
 use FS::UID qw( getotaker dbh driver_name );
 use FS::Record qw( qsearchs qsearch dbdef );
-use FS::Misc qw( send_email generate_ps do_print );
+use FS::Misc qw( generate_email send_email generate_ps do_print );
 use FS::Msgcat qw(gettext);
 use FS::cust_pkg;
 use FS::cust_svc;
@@ -4822,6 +4822,122 @@
 
 }
 
+=item email_search_sql HASHREF
+
+(Class method)
+
+Emails a notice to the specified customers.
+
+Valid parameters are those of the L<search_sql> method, plus the following:
+
+=over 4
+
+=item from
+
+From: address
+
+=item subject
+
+Email Subject:
+
+=item html_body
+
+HTML body
+
+=item text_body
+
+Text body
+
+=item job
+
+Optional job queue job for status updates.
+
+=back
+
+Returns an error message, or false for success.
+
+If an error occurs during any email, stops the enture send and returns that
+error.  Presumably if you're getting SMTP errors aborting is better than 
+retrying everything.
+
+=cut
+
+sub email_search_sql {
+  my($class, $params) = @_;
+
+  my $from = delete $params->{from};
+  my $subject = delete $params->{subject};
+  my $html_body = delete $params->{html_body};
+  my $text_body = delete $params->{text_body};
+
+  my $job = delete $params->{'job'};
+
+  my $sql_query = $class->search_sql($params);
+
+  my $count_query   = delete($sql_query->{'count_query'});
+  my $count_sth = dbh->prepare($count_query)
+    or die "Error preparing $count_query: ". dbh->errstr;
+  $count_sth->execute
+    or die "Error executing $count_query: ". $count_sth->errstr;
+  my $count_arrayref = $count_sth->fetchrow_arrayref;
+  my $num_cust = $count_arrayref->[0];
+
+  #my @extra_headers = @{ delete($sql_query->{'extra_headers'}) };
+  #my @extra_fields  = @{ delete($sql_query->{'extra_fields'})  };
+
+
+  my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo
+
+  #eventually order+limit magic to reduce memory use?
+  foreach my $cust_main ( qsearch($sql_query) ) {
+
+    my $to = $cust_main->invoicing_list_emailonly_scalar;
+    next unless $to;
+
+    my $error = send_email(
+      generate_email(
+        'from'      => $from,
+        'to'        => $to,
+        'subject'   => $subject,
+        'html_body' => $html_body,
+        'text_body' => $text_body,
+      )
+    );
+    return $error if $error;
+
+    if ( $job ) { #progressbar foo
+      $num++;
+      if ( time - $min_sec > $last ) {
+        my $error = $job->update_statustext(
+          int( 100 * $num / $num_cust )
+        );
+        die $error if $error;
+        $last = time;
+      }
+    }
+
+  }
+
+  return '';
+}
+
+use Storable qw(thaw);
+use Data::Dumper;
+use MIME::Base64;
+sub process_email_search_sql {
+  my $job = shift;
+  #warn "$me process_re_X $method for job $job\n" if $DEBUG;
+
+  my $param = thaw(decode_base64(shift));
+  warn Dumper($param) if $DEBUG;
+
+  $param->{'job'} = $job;
+
+  my $error = FS::cust_main->email_search_sql( $param );
+  die $error if $error;
+
+}
+
 =item fuzzy_search FUZZY_HASHREF [ HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ ]
 
 Performs a fuzzy (approximate) search and returns the matching FS::cust_main



More information about the freeside-commits mailing list