[freeside-commits] branch FREESIDE_2_3_BRANCH updated. 0f29353b8cc466ea58115da3aa9a58b50b8d3d08

Mark Wells mark at 420.am
Tue May 22 00:24:52 PDT 2012


The branch, FREESIDE_2_3_BRANCH has been updated
       via  0f29353b8cc466ea58115da3aa9a58b50b8d3d08 (commit)
      from  38653b6cddc970f630790e0bf9f33cf9b17b69bc (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 0f29353b8cc466ea58115da3aa9a58b50b8d3d08
Author: Mark Wells <mark at freeside.biz>
Date:   Tue May 22 00:23:53 2012 -0700

    non-billco FTP invoice spool upload, #16382

diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index 35279d6..91abd2a 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -3065,7 +3065,14 @@ and customer address. Include units.',
     'type'        => 'checkbox',
   },
 
-  {
+    {
+    'key'         => 'cust_bill-ftp_spool',
+    'section'     => 'invoicing',
+    'description' => 'Enable FTP upload of the invoice spool during daily processing',
+    'type'        => 'checkbox',
+  },
+
+{
     'key'         => 'svc_acct-usage_suspend',
     'section'     => 'billing',
     'description' => 'Suspends the package an account belongs to when svc_acct.seconds or a bytecount is decremented to 0 or below (accounts with an empty seconds and up|down|totalbytes value are ignored).  Typically used in conjunction with prepaid packages and freeside-sqlradius-radacctd.',
diff --git a/FS/FS/Cron/upload.pm b/FS/FS/Cron/upload.pm
index 877b07f..5fe8131 100644
--- a/FS/FS/Cron/upload.pm
+++ b/FS/FS/Cron/upload.pm
@@ -39,43 +39,99 @@ sub upload {
 
   warn "$me upload called\n" if $DEBUG;
 
-  my $conf = new FS::Conf;
-  my @agent = grep { $conf->config( 'billco-username', $_->agentnum, 1 ) }
-              grep { $conf->config( 'billco-password', $_->agentnum, 1 ) }
-              qsearch( 'agent', {} );
+  my @tasks;
 
   my $date =  time2str('%Y%m%d%H%M%S', $^T); # more?
 
-  @agent = grep { $_ == $opt{'a'} } @agent if $opt{'a'};
+  my $conf = new FS::Conf;
 
-  foreach my $agent ( @agent ) {
+  my @agents = $opt{'a'} ? FS::agent->by_key($opt{'a'}) : qsearch('agent', {});
+
+  if ( $conf->exists('cust_bill-ftp_spool') ) {
+    my $url = $conf->config('cust_bill-ftpdir');
+    $url = "/$url" unless $url =~ m[^/];
+    $url = 'ftp://' . $conf->config('cust_bill-ftpserver') . $url;
+
+    my $format = $conf->config('cust_bill-ftpformat');
+    my $username = $conf->config('cust_bill-ftpusername');
+    my $password = $conf->config('cust_bill-ftppassword');
+
+    my %task = (
+      'date'      => $date,
+      'l'         => $opt{'l'},
+      'm'         => $opt{'m'},
+      'v'         => $opt{'v'},
+      'username'  => $username,
+      'password'  => $password,
+      'url'       => $url,
+      'format'    => $format,
+    );
+
+    if ( $conf->exists('cust_bill-spoolagent') ) {
+      # then push each agent's spool separately
+      foreach ( @agents ) {
+        push @tasks, { %task, 'agentnum' => $_->agentnum };
+      }
+    }
+    elsif ( $opt{'a'} ) {
+      warn "Per-agent processing, but cust_bill-spoolagent is not enabled.\nSkipped invoice upload.\n";
+    }
+    else {
+      push @tasks, \%task;
+    }
+  }
 
-    my $agentnum = $agent->agentnum;
+  else { #check each agent for billco upload settings
+
+    my %task = (
+      'date'      => $date,
+      'l'         => $opt{'l'},
+      'm'         => $opt{'m'},
+      'v'         => $opt{'v'},
+    );
+
+    foreach (@agents) {
+      my $agentnum = $_->agentnum;
+
+      if ( $conf->config( 'billco-username', $agentnum, 1 ) ) {
+        my $username = $conf->config('billco-username', $agentnum, 1);
+        my $password = $conf->config('billco-password', $agentnum, 1);
+        my $clicode  = $conf->config('billco-clicode',  $agentnum, 1);
+        my $url      = $conf->config('billco-url',      $agentnum);
+        push @tasks, {
+          %task,
+          'agentnum' => $agentnum,
+          'username' => $username,
+          'password' => $password,
+          'url'      => $url,
+          'clicode'  => $clicode,
+          'format'   => 'billco',
+        };
+      }
+    } # foreach @agents
+
+  } #!if cust_bill-ftp_spool
+
+  foreach (@tasks) {
+
+    my $agentnum = $_->{agentnum};
 
     if ( $opt{'m'} ) {
 
       if ( $opt{'r'} ) {
         warn "DRY RUN: would add agent $agentnum for queued upload\n";
       } else {
-
         my $queue = new FS::queue {
-          'job'      => 'FS::Cron::upload::billco_upload',
+          'job'      => 'FS::Cron::upload::spool_upload',
         };
-        my $error = $queue->insert(
-                                    'agentnum' => $agentnum,
-                                    'date'     => $date,
-                                    'l'        => $opt{'l'} || '',
-                                    'm'        => $opt{'m'} || '',
-                                    'v'        => $opt{'v'} || '',
-                                  );
-
+        my $error = $queue->insert( %$_ );
       }
 
     } else {
 
-      eval "&billco_upload( 'agentnum' => $agentnum, 'date' => $date );";
-      warn "billco_upload failed: $@\n"
-        if ( $@ );
+      eval { spool_upload(%$_) };
+      warn "spool_upload failed: $@\n"
+        if $@;
 
     }
 
@@ -83,25 +139,21 @@ sub upload {
 
 }
 
-sub billco_upload {
+sub spool_upload {
   my %opt = @_;
 
-  warn "$me billco_upload called\n" if $DEBUG;
+  warn "$me spool_upload called\n" if $DEBUG;
   my $conf = new FS::Conf;
   my $dir = '%%%FREESIDE_EXPORT%%%/export.'. $FS::UID::datasrc. '/cust_bill';
 
   my $agentnum = $opt{agentnum} or die "no agentnum provided\n";
-  my $url      = $conf->config( 'billco-url', $agentnum )
-    or die "no url for agent $agentnum\n";
-  my $username = $conf->config( 'billco-username', $agentnum, 1 )
-    or die "no username for agent $agentnum\n";
-  my $password = $conf->config( 'billco-password', $agentnum, 1 )
-    or die "no password for agent $agentnum\n";
-  my $clicode  = $conf->config( 'billco-clicode', $agentnum, 1 );
-    #or die "no clicode for agent $agentnum\n";
+  my $url      = $opt{url} or die "no url for agent $agentnum\n";
+  $url =~ s/^\s+//; $url =~ s/\s+$//;
+
+  my $username = $opt{username} or die "no username for agent $agentnum\n";
+  my $password = $opt{password} or die "no password for agent $agentnum\n";
 
   die "no date provided\n" unless $opt{date};
-  my $zipfile  = "$dir/agentnum$agentnum-$opt{date}.zip";
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
@@ -118,82 +170,119 @@ sub billco_upload {
     or die "no such agent: $agentnum";
   $agent->select_for_update; #mutex 
 
-  unless ( -f "$dir/agentnum$agentnum-header.csv" ||
-           -f "$dir/agentnum$agentnum-detail.csv" )
-  {
-    warn "$me neither $dir/agentnum$agentnum-header.csv nor ".
-         "$dir/agentnum$agentnum-detail.csv found\n" if $DEBUG;
-    $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-    return;
-  }
+  if ( $opt{'format'} eq 'billco' ) {
+
+    my $zipfile  = "$dir/agentnum$agentnum-$opt{date}.zip";
 
-  # a better way?
-  if ($opt{m}) {
-    my $sql = "SELECT count(*) FROM queue LEFT JOIN cust_main USING(custnum) ".
-      "WHERE queue.job='FS::cust_main::queued_bill' AND cust_main.agentnum = ?";
-    my $sth = $dbh->prepare($sql) or die $dbh->errstr;
-    while (1) {
-      $sth->execute( $agentnum )
-        or die "Unexpected error executing statement $sql: ". $sth->errstr;
-      last if $sth->fetchow_arrayref->[0];
-      sleep 300;
+    unless ( -f "$dir/agentnum$agentnum-header.csv" ||
+             -f "$dir/agentnum$agentnum-detail.csv" )
+    {
+      warn "$me neither $dir/agentnum$agentnum-header.csv nor ".
+           "$dir/agentnum$agentnum-detail.csv found\n" if $DEBUG;
+      $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+      return;
     }
-  }
 
-  foreach ( qw ( header detail ) ) {
-    rename "$dir/agentnum$agentnum-$_.csv",
-           "$dir/agentnum$agentnum-$opt{date}-$_.csv";
-  }
+    # a better way?
+    if ($opt{m}) {
+      my $sql = "SELECT count(*) FROM queue LEFT JOIN cust_main USING(custnum) ".
+        "WHERE queue.job='FS::cust_main::queued_bill' AND cust_main.agentnum = ?";
+      my $sth = $dbh->prepare($sql) or die $dbh->errstr;
+      while (1) {
+        $sth->execute( $agentnum )
+          or die "Unexpected error executing statement $sql: ". $sth->errstr;
+        last if $sth->fetchrow_arrayref->[0];
+        sleep 300;
+      }
+    }
+
+    foreach ( qw ( header detail ) ) {
+      rename "$dir/agentnum$agentnum-$_.csv",
+             "$dir/agentnum$agentnum-$opt{date}-$_.csv";
+    }
+
+    my $command = "cd $dir; zip $zipfile ".
+                  "agentnum$agentnum-$opt{date}-header.csv ".
+                  "agentnum$agentnum-$opt{date}-detail.csv";
+
+    system($command) and die "$command failed\n";
 
-  my $command = "cd $dir; zip $zipfile ".
-                "agentnum$agentnum-$opt{date}-header.csv ".
-                "agentnum$agentnum-$opt{date}-detail.csv";
+    unlink "agentnum$agentnum-$opt{date}-header.csv",
+           "agentnum$agentnum-$opt{date}-detail.csv";
 
-  system($command) and die "$command failed\n";
+    if ( $url =~ /^http/i ) {
 
-  unlink "agentnum$agentnum-$opt{date}-header.csv",
-         "agentnum$agentnum-$opt{date}-detail.csv";
+      my $ua = new LWP::UserAgent;
+      my $res = $ua->request( POST( $url,
+                                    'Content_Type' => 'form-data',
+                                    'Content' => [ 'username' => $username,
+                                                   'pass'     => $password,
+                                                   'custid'   => $username,
+                                                   'clicode'  => $opt{clicode},
+                                                   'file1'    => [ $zipfile ],
+                                                 ],
+                                  )
+                            );
 
-  if ( $url =~ /^http/i ) {
+      die "upload failed: ". $res->status_line. "\n"
+        unless $res->is_success;
 
-    my $ua = new LWP::UserAgent;
-    my $res = $ua->request( POST( $url,
-                                  'Content_Type' => 'form-data',
-                                  'Content' => [ 'username' => $username,
-                                                 'pass'     => $password,
-                                                 'custid'   => $username,
-                                                 'clicode'  => $clicode,
-                                                 'file1'    => [ $zipfile ],
-                                               ],
-                                )
-                          );
+    } elsif ( $url =~ /^ftp:\/\/([\w\.]+)(\/.*)$/i ) {
 
-    die "upload failed: ". $res->status_line. "\n"
-      unless $res->is_success;
+      my($hostname, $path) = ($1, $2);
 
-  } elsif ( $url =~ /^ftp:\/\/([\w\.]+)(\/.*)$/i ) {
+      my $ftp = new Net::FTP($hostname)
+        or die "can't connect to $hostname: $@\n";
+      $ftp->login($username, $password)
+        or die "can't login to $hostname: ". $ftp->message."\n";
+      unless ( $ftp->cwd($path) ) {
+        my $msg = "can't cd $path on $hostname: ". $ftp->message. "\n";
+        ( $path eq '/' ) ? warn $msg : die $msg;
+      }
+      $ftp->binary
+        or die "can't set binary mode on $hostname\n";
+
+      $ftp->put($zipfile)
+        or die "can't put $zipfile: ". $ftp->message. "\n";
 
-    my($hostname, $path) = ($1, $2);
+      $ftp->quit;
 
-    my $ftp = new Net::FTP($hostname)
-      or die "can't connect to $hostname: $@\n";
-    $ftp->login($username, $password)
-      or die "can't login to $hostname: ". $ftp->message."\n";
-    unless ( $ftp->cwd($path) ) {
-      my $msg = "can't cd $path on $hostname: ". $ftp->message. "\n";
-      ( $path eq '/' ) ? warn $msg : die $msg;
+    } else {
+      die "unknown scheme in URL $url\n";
     }
-    $ftp->binary
-      or die "can't set binary mode on $hostname\n";
 
-    $ftp->put($zipfile)
-      or die "can't put $zipfile: ". $ftp->message. "\n";
+  } else { #$opt{format} ne 'billco'
 
-    $ftp->quit;
+    my $date = $opt{date};
+    my $file = $opt{agentnum} ? "agentnum$opt{agentnum}" : 'spool'; #.csv
+    unless ( -f "$dir/$file.csv" ) {
+      warn "$me $dir/$file.csv not found\n" if $DEBUG;
+      $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+      return;
+    }
+    rename "$dir/$file.csv", "$dir/$file-$date.csv";
+
+    #ftp only for now
+    if ( $url =~ m{^ftp://([\w\.]+)(/.*)$}i ) {
+
+      my ($hostname, $path) = ($1, $2);
+      my $ftp = new Net::FTP ($hostname)
+        or die "can't connect to $hostname: $@\n";
+      $ftp->login($username, $password)
+        or die "can't login to $hostname: ".$ftp->message."\n";
+      unless ( $ftp->cwd($path) ) {
+        my $msg = "can't cd $path on $hostname: ".$ftp->message."\n";
+        ( $path eq '/' ) ? warn $msg : die $msg;
+      }
+      chdir($dir);
+      $ftp->put("$file-$date.csv")
+        or die "can't put $file-$date.csv: ".$ftp->message."\n";
+      $ftp->quit;
 
-  } else {
-    die "unknown scheme in URL $url\n";
-  }
+    } else {
+      die "malformed FTP URL $url\n";
+    }
+  } #opt{format}
 
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
   '';

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

Summary of changes:
 FS/FS/Conf.pm        |    9 ++-
 FS/FS/Cron/upload.pm |  271 +++++++++++++++++++++++++++++++++-----------------
 2 files changed, 188 insertions(+), 92 deletions(-)




More information about the freeside-commits mailing list