[freeside-commits] branch FREESIDE_3_BRANCH updated. 92fec248ff22a3c2c805e85d94daaff70a53d960

Mark Wells mark at 420.am
Tue Aug 27 17:01:18 PDT 2013


The branch, FREESIDE_3_BRANCH has been updated
       via  92fec248ff22a3c2c805e85d94daaff70a53d960 (commit)
      from  a223a9cc2dca2529a77fa2a45c7c088b59a66f61 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 92fec248ff22a3c2c805e85d94daaff70a53d960
Author: Mark Wells <mark at freeside.biz>
Date:   Tue Aug 27 16:59:37 2013 -0700

    send credit card expiration alerts with billing events, #13201

diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index de32ee3..f831af8 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -778,8 +778,8 @@ sub reason_type_options {
 
   {
     'key'         => 'alert_expiration',
-    'section'     => 'notification',
-    'description' => 'Enable alerts about billing method expiration (i.e. expiring credit cards).',
+    'section'     => 'deprecated',
+    'description' => 'Enable alerts about credit card expiration.  This is obsolete and no longer works.',
     'type'        => 'checkbox',
     'per_agent'   => 1,
   },
@@ -794,7 +794,7 @@ sub reason_type_options {
   
   {
     'key'         => 'alerter_msgnum',
-    'section'     => 'notification',
+    'section'     => 'deprecated',
     'description' => 'Template to use for credit card expiration alerts.',
     %msg_template_options,
   },
diff --git a/FS/FS/Cron/alert_expiration.pm b/FS/FS/Cron/alert_expiration.pm
deleted file mode 100644
index 5961e61..0000000
--- a/FS/FS/Cron/alert_expiration.pm
+++ /dev/null
@@ -1,190 +0,0 @@
-package FS::Cron::alert_expiration;
-
-use vars qw( @ISA @EXPORT_OK);
-use Exporter;
-use FS::Record qw(qsearch qsearchs);
-use FS::Conf;
-use FS::cust_main;
-use FS::Misc;
-use Time::Local;
-use Date::Parse qw(str2time);
-
-
- at ISA = qw( Exporter );
- at EXPORT_OK = qw( alert_expiration );
-
-my $warning_time = 30 * 24 * 60 * 60;
-my $urgent_time = 15 * 24 * 60 * 60;
-my $panic_time = 5 * 24 * 60 * 60;
-my $window_time = 24 * 60 * 60;
-
-sub alert_expiration {
-  my $conf = new FS::Conf;
-  my $smtpmachine = $conf->config('smtpmachine');
-  
-  my %opt = @_;
-  my ($_date) = $opt{'d'} ? str2time($opt{'d'}) : $^T;
-  $_date += $opt{'y'} * 86400 if $opt{'y'};
-  my ($sec, $min, $hour, $mday, $mon, $year) = (localtime($_date)) [0..5];
-  $mon++;
-
-  my $debug = 0;
-  $debug = 1 if $opt{'v'};
-  $debug = $opt{'l'} if $opt{'l'};
-
-  $FS::cust_main::DEBUG = $debug;
-
-  # Get a list of customers.
- 
-  my %limit;
-  $limit{'agentnum'} = $opt{'a'} if $opt{'a'};
-  $limit{'payby'}    = $opt{'p'} if $opt{'p'};
-
-  my @customers;
-
-  if(my @custnums = @ARGV) {
-    # We're given an explicit list of custnums, so select those.  Then check against 
-    # -a and -p to avoid doing anything unexpected.
-    foreach (@custnums) {
-      my $customer = FS::cust_main->by_key($_);
-      if($customer and (!$opt{'a'} or $customer->agentnum == $opt{'a'})
-                   and (!$opt{'p'} or $customer->payby eq $opt{'p'}) ) {
-        push @customers, $customer;
-      }
-    }
-  }
-  else { # no @ARGV
-    @customers = qsearch('cust_main', \%limit);
-  }
-  return if(!@customers);
-  foreach my $customer (@customers) {
-    next if !($customer->ncancelled_pkgs); # skip inactive customers
-    my $paydate = $customer->paydate;
-    next if $paydate =~ /^\s*$/; # skip empty expiration dates
-    
-    my $custnum = $customer->custnum;
-    my $first   = $customer->first;
-    my $last    = $customer->last;
-    my $company = $customer->company;
-    my $payby   = $customer->payby;
-    my $payinfo = $customer->payinfo;
-    my $daytime = $customer->daytime;
-    my $night   = $customer->night;
-
-    my ($paymonth, $payyear) = $customer->paydate_monthyear;
-    $paymonth--; # localtime() convention
-    $payday = 1; # This is enforced by FS::cust_main::check.
-    my $expire_time;
-    if($payby eq 'CARD' || $payby eq 'DCRD') {
-      # Credit cards expire at the end of the month/year.
-      if($paymonth == 11) {
-        $payyear++;
-        $paymonth = 0;
-      } else {
-        $paymonth++;
-      }
-      $expire_time = timelocal(0,0,0,$payday,$paymonth,$payyear) - 1;
-    }
-    else {
-      $expire_time = timelocal(0,0,0,$payday,$paymonth,$payyear);
-    }
-    
-    if (grep { $expire_time < $_date + $_ &&
-               $expire_time > $_date + $_ - $window_time } 
-               ($warning_time, $urgent_time, $panic_time) ) {
-      # Send an expiration notice.
-      my $agentnum = $customer->agentnum;
-      my $error = '';
-
-      my $msgnum = $conf->config('alerter_msgnum', $agentnum);
-      if ( $msgnum ) { # new hotness
-        my $msg_template = qsearchs('msg_template', { msgnum => $msgnum } );
-        $customer->setfield('expdate', $expire_time);
-        $error = $msg_template->send('cust_main' => $customer,
-                                     'object'    => $customer);
-      }
-      else { #!$msgnum, the hard way
-        $mail_sender = $conf->config('invoice_from', $agentnum);
-        $failure_recipient = $conf->config('invoice_from', $agentnum) 
-          || 'postmaster';
-       
-        my @alerter_template = $conf->config('alerter_template', $agentnum)
-          or die 'cannot load config file alerter_template';
-
-        my $alerter = new Text::Template(TYPE   => 'ARRAY',
-                                         SOURCE => [ 
-                                           map "$_\n", @alerter_template
-                                           ])
-          or die "can't create Text::Template object: $Text::Template::ERROR";
-
-        $alerter->compile()
-          or die "can't compile template: $Text::Template::ERROR";
-        
-        my @invoicing_list = $customer->invoicing_list;
-        my @to_addrs = grep { $_ ne 'POST' } @invoicing_list;
-        if(@to_addrs) {
-          # Set up template fields.
-          my %fill_in;
-          $fill_in{$_} = $customer->getfield($_) 
-            foreach(qw(first last company));
-          $fill_in{'expdate'} = $expire_time;
-          $fill_in{'company_name'} = $conf->config('company_name', $agentnum);
-          $fill_in{'company_address'} =
-            join("\n",$conf->config('company_address',$agentnum))."\n";
-          if($payby eq 'CARD' || $payby eq 'DCRD') {
-            $fill_in{'payby'} = "credit card (".
-              substr($customer->payinfo, 0, 2) . "xxxxxxxxxx" .
-              substr($payinfo, -4) . ")";
-          }
-          elsif($payby eq 'COMP') {
-            $fill_in{'payby'} = 'complimentary account';
-          }
-          else {
-            $fill_in{'payby'} = 'current method';
-          }
-          # Send it already!
-          $error = FS::Misc::send_email ( 
-            from    =>  $mail_sender,
-            to      =>  [ @to_addrs ],
-            subject =>  'Billing Arrangement Expiration',
-            body    =>  [ $alerter->fill_in( HASH => \%fill_in ) ],
-          );
-      } 
-      else { # if(@to_addrs)
-        push @{$agent_failure_body{$customer->agentnum}},
-          sprintf(qq{%5d %-32.32s %4s %10s %12s %12s},
-            $custnum,
-            $first . " " . $last . "   " . $company,
-            $payby,
-            $paydate,
-            $daytime,
-            $night );
-      }
-    } # if($msgnum)
-    
-# should we die here rather than report failure as below?
-    die "can't send expiration alert: $error"
-      if $error;
-    
-    } # if(expired)
-  } # foreach(@customers)
-
-  # Failure notification
-  foreach my $agentnum (keys %agent_failure_body) {
-    $mail_sender = $conf->config('invoice_from', $agentnum)
-      if($conf->exists('invoice_from', $agentnum));
-    $failure_recipient = $conf->config('invoice_from', $agentnum)
-      if($conf->exists('invoice_from', $agentnum));
-    my $error = FS::Misc::send_email (
-      from    =>  $mail_sender,
-      to      =>  $failure_recipient,
-      subject =>  'Unnotified Billing Arrangement Expirations',
-      body    =>  [ @{$agent_failure_body{$agentnum}} ],
-      );
-    die "can't send alerter failure email to $failure_recipient: $error"
-      if $error;
-  }
-
-}
-
-1;
diff --git a/FS/FS/msg_template.pm b/FS/FS/msg_template.pm
index bef2b4b..4e1f4da 100644
--- a/FS/FS/msg_template.pm
+++ b/FS/FS/msg_template.pm
@@ -732,6 +732,64 @@ sub _upgrade_data {
         $conf->delete($subject, $agentnum) if $subject;
       }
     }
+
+    if ( $conf->exists('alert_expiration', $agentnum) ) {
+      my $msgnum = $conf->exists('alerter_msgnum', $agentnum);
+      my $template = FS::msg_template->by_key($msgnum) if $msgnum;
+      if (!$template) {
+        warn "template for alerter_msgnum $msgnum not found\n";
+        next;
+      }
+      # this is now a set of billing events
+      foreach my $days (30, 15, 5) {
+        my $event = FS::part_event->new({
+            'agentnum'    => $agentnum,
+            'event'       => "Card expiration warning - $days days",
+            'eventtable'  => 'cust_main',
+            'check_freq'  => '1d',
+            'action'      => 'notice',
+            'disabled'    => 'Y', #initialize first
+        });
+        my $error = $event->insert( 'msgnum' => $msgnum );
+        if ($error) {
+          warn "error creating expiration alert event:\n$error\n\n";
+          next;
+        }
+        # make it work like before:
+        # only send each warning once before the card expires,
+        # only warn active customers,
+        # only warn customers with CARD/DCRD,
+        # only warn customers who get email invoices
+        my %conds = (
+          'once_every'          => { 'run_delay' => '30d' },
+          'cust_paydate_within' => { 'within' => $days.'d' },
+          'cust_status'         => { 'status' => { 'active' => 1 } },
+          'payby'               => { 'payby'  => { 'CARD' => 1,
+                                                   'DCRD' => 1, }
+                                   },
+          'message_email'       => {},
+        );
+        foreach (keys %conds) {
+          my $condition = FS::part_event_condition->new({
+              'conditionname' => $_,
+              'eventpart'     => $event->eventpart,
+          });
+          $error = $condition->insert( %{ $conds{$_} });
+          if ( $error ) {
+            warn "error creating expiration alert event:\n$error\n\n";
+            next;
+          }
+        }
+        $error = $event->initialize;
+        if ( $error ) {
+          warn "expiration alert event was created, but not initialized:\n$error\n\n";
+        }
+      } # foreach $days
+      $conf->delete('alerter_msgnum', $agentnum);
+      $conf->delete('alert_expiration', $agentnum);
+
+    } # if alerter_msgnum
+
   }
   foreach my $msg_template ( qsearch('msg_template', {}) ) {
     if ( $msg_template->subject || $msg_template->body ) {
diff --git a/FS/FS/part_event/Condition/cust_paydate_within.pm b/FS/FS/part_event/Condition/cust_paydate_within.pm
index 4808e90..bfe3e84 100644
--- a/FS/FS/part_event/Condition/cust_paydate_within.pm
+++ b/FS/FS/part_event/Condition/cust_paydate_within.pm
@@ -23,7 +23,7 @@ sub eventtable_hashref {
 
 sub option_fields {
   (
-    'within'  =>  { 'label'   => 'Expiration date within',
+    'within'  =>  { 'label'   => 'Credit card will expire within',
                     'type'    => 'freq',
                   },
   );
@@ -32,14 +32,17 @@ sub option_fields {
 sub condition {
   my( $self, $cust_main, %opt ) = @_;
   my $expire_time = $cust_main->paydate_epoch or return 0;
-  $opt{'time'} >= $self->option_age_from('within', $expire_time);
+  $opt{'time'} >= $self->option_age_from('within', $expire_time) and
+  $opt{'time'} <  $expire_time;
 }
 
 sub condition_sql {
   my ($self, $table, %opt) = @_;
   my $expire_time = FS::cust_main->paydate_epoch_sql or return 'true';
-  $opt{'time'} . ' >= ' .  
-    $self->condition_sql_option_age_from('within', $expire_time);
+  ' ( '. $opt{'time'} . ' >= ' .  
+    $self->condition_sql_option_age_from('within', $expire_time) .
+    ' AND ' . $opt{'time'} . ' < ' . $expire_time . ' ) ';
+
 }
 
 1;
diff --git a/FS/bin/freeside-daily b/FS/bin/freeside-daily
index d613258..e6cb0dc 100755
--- a/FS/bin/freeside-daily
+++ b/FS/bin/freeside-daily
@@ -38,10 +38,13 @@ upload(%opt);
 use FS::Cron::set_lata_have_usage qw(set_lata_have_usage);
 set_lata_have_usage(%opt);
 
-# Send alerts about upcoming credit card expiration.
-use FS::Cron::alert_expiration qw(alert_expiration);
+# we used to send alerts about upcoming credit card expiration here
 my $conf = new FS::Conf;
-alert_expiration(%opt) if($conf->exists('alert_expiration'));
+if($conf->exists('alert_expiration')) {
+  warn "WARNING: the alert_expiration option is obsolete.  If you ran 
+  freeside-upgrade, it should have configured credit card expiration alerts 
+  as billing events.\n";
+}
 
 #what to do about the below when using -m?  that is the question.
 

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/Conf.pm                                     |    6 +-
 FS/FS/Cron/alert_expiration.pm                    |  190 ---------------------
 FS/FS/msg_template.pm                             |   58 +++++++
 FS/FS/part_event/Condition/cust_paydate_within.pm |   11 +-
 FS/bin/freeside-daily                             |    9 +-
 5 files changed, 74 insertions(+), 200 deletions(-)
 delete mode 100644 FS/FS/Cron/alert_expiration.pm




More information about the freeside-commits mailing list