summaryrefslogtreecommitdiff
path: root/FS/FS/Cron
diff options
context:
space:
mode:
authorMark Wells <mark@freeside.biz>2012-06-13 16:18:49 -0700
committerMark Wells <mark@freeside.biz>2012-06-13 16:18:49 -0700
commit9ef78be87df0f0f880ff5d903ed6243b67369cf0 (patch)
treee69278b1e33baf2b9c0356ed31435fc0f0188b01 /FS/FS/Cron
parentdaa09251fec52517b630b3f6935041dc7c795f90 (diff)
table of FTP targets for invoice spool upload, #17620
Diffstat (limited to 'FS/FS/Cron')
-rw-r--r--FS/FS/Cron/upload.pm290
1 files changed, 185 insertions, 105 deletions
diff --git a/FS/FS/Cron/upload.pm b/FS/FS/Cron/upload.pm
index c266797..51e0d68 100644
--- a/FS/FS/Cron/upload.pm
+++ b/FS/FS/Cron/upload.pm
@@ -9,6 +9,8 @@ use FS::Record qw( qsearch qsearchs );
use FS::Conf;
use FS::queue;
use FS::agent;
+use FS::Misc qw( send_email ); #for bridgestone
+use FS::ftp_target;
use LWP::UserAgent;
use HTTP::Request;
use HTTP::Request::Common;
@@ -47,70 +49,50 @@ sub upload {
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 %task = (
+ 'date' => $date,
+ 'l' => $opt{'l'},
+ 'm' => $opt{'m'},
+ 'v' => $opt{'v'},
+ );
+
+ my @agentnums = ('', map {$_->agentnum} @agents);
+
+ foreach my $target (qsearch('ftp_target', {})) {
+ # We don't know here if it's spooled on a per-agent basis or not.
+ # (It could even be both, via different events.) So queue up an
+ # upload for each agent, plus one with null agentnum, and we'll
+ # upload as many files as we find.
+ foreach my $a (@agentnums) {
+ push @tasks, {
+ %task,
+ 'agentnum' => $a,
+ 'targetnum' => $target->targetnum,
+ 'handling' => $target->handling,
+ };
}
}
- 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
+ # deprecated billco method
+ 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,
+ 'handling' => 'billco',
+ };
+ }
+ } # foreach @agents
foreach (@tasks) {
@@ -146,14 +128,7 @@ sub spool_upload {
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 = $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 $date = $opt{date} or die "no date provided\n";
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
@@ -166,23 +141,34 @@ sub spool_upload {
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
- my $agent = qsearchs( 'agent', { agentnum => $agentnum } )
- or die "no such agent: $agentnum";
- $agent->select_for_update; #mutex
+ my $agentnum = $opt{agentnum};
+ my $agent;
+ if ( $agentnum ) {
+ $agent = qsearchs( 'agent', { agentnum => $agentnum } )
+ or die "no such agent: $agentnum";
+ $agent->select_for_update; #mutex
+ }
- if ( $opt{'format'} eq 'billco' ) {
+ if ( $opt{'handling'} eq 'billco' ) {
- my $zipfile = "$dir/agentnum$agentnum-$opt{date}.zip";
+ my $file = "agentnum$agentnum";
+ my $zipfile = "$dir/$file-$date.zip";
- unless ( -f "$dir/agentnum$agentnum-header.csv" ||
- -f "$dir/agentnum$agentnum-detail.csv" )
+ unless ( -f "$dir/$file-header.csv" ||
+ -f "$dir/$file-detail.csv" )
{
- warn "$me neither $dir/agentnum$agentnum-header.csv nor ".
- "$dir/agentnum$agentnum-detail.csv found\n" if $DEBUG;
+ warn "$me neither $dir/$file-header.csv nor ".
+ "$dir/$file-detail.csv found\n" if $DEBUG > 1;
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
return;
}
+ 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";
+
# a better way?
if ($opt{m}) {
my $sql = "SELECT count(*) FROM queue LEFT JOIN cust_main USING(custnum) ".
@@ -197,18 +183,18 @@ sub spool_upload {
}
foreach ( qw ( header detail ) ) {
- rename "$dir/agentnum$agentnum-$_.csv",
- "$dir/agentnum$agentnum-$opt{date}-$_.csv";
+ rename "$dir/$file-$_.csv",
+ "$dir/$file-$date-$_.csv";
}
my $command = "cd $dir; zip $zipfile ".
- "agentnum$agentnum-$opt{date}-header.csv ".
- "agentnum$agentnum-$opt{date}-detail.csv";
+ "$file-$date-header.csv ".
+ "$file-$date-detail.csv";
system($command) and die "$command failed\n";
- unlink "agentnum$agentnum-$opt{date}-header.csv",
- "agentnum$agentnum-$opt{date}-detail.csv";
+ unlink "$file-$date-header.csv",
+ "$file-$date-detail.csv";
if ( $url =~ /^http/i ) {
@@ -251,38 +237,132 @@ sub spool_upload {
die "unknown scheme in URL $url\n";
}
- } else { #$opt{format} ne 'billco'
+ }
+ else { #not billco
+
+ my $targetnum = $opt{targetnum};
+ my $ftp_target = FS::ftp_target->by_key($targetnum)
+ or die "FTP target $targetnum not found\n";
+
+ $dir .= "/target$targetnum";
+ chdir($dir);
+
+ my $file = $agentnum ? "agentnum$agentnum" : 'spool'; #.csv
- 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;
+ warn "$me $dir/$file.csv not found\n" if $DEBUG > 1;
$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 ) {
+ if ( $opt{'handling'} eq 'bridgestone' ) {
- 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;
+ my $prefix = $conf->config('bridgestone-prefix', $agentnum);
+ unless ( $prefix ) {
+ warn "$me agent $agentnum has no bridgestone-prefix, skipped\n";
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ return;
}
- chdir($dir);
- $ftp->put("$file-$date.csv")
- or die "can't put $file-$date.csv: ".$ftp->message."\n";
- $ftp->quit;
- } else {
- die "malformed FTP URL $url\n";
+ my $seq = $conf->config('bridgestone-batch_counter', $agentnum) || 1;
+
+ # extract zip code
+ join(' ',$conf->config('company_address', $agentnum)) =~
+ /(\d{5}(\-\d{4})?)\s*$/;
+ my $ourzip = $1 || ''; #could be an explicit option if really needed
+ $ourzip =~ s/\D//;
+ my $newfile = sprintf('%s_%s_%0.6d.dat',
+ $prefix,
+ time2str('%Y%m%d', time),
+ $seq);
+ warn "copying spool to $newfile\n" if $DEBUG;
+
+ my ($in, $out);
+ open $in, '<', "$dir/$file-$date.csv"
+ or die "unable to read $file-$date.csv\n";
+ open $out, '>', "$dir/$newfile" or die "unable to write $newfile\n";
+ #header--not sure how much of this generalizes at all
+ my $head = sprintf(
+ "%-6s%-4s%-27s%-6s%0.6d%-5s%-9s%-9s%-7s%0.8d%-7s%0.6d\n",
+ ' COMP:', 'VISP', '', ',SEQ#:', $seq, ',ZIP:', $ourzip, ',VERS:1.1',
+ ',RUNDT:', time2str('%m%d%Y', $^T),
+ ',RUNTM:', time2str('%H%M%S', $^T),
+ );
+ warn "HEADER: $head" if $DEBUG;
+ print $out $head;
+
+ my $rows = 0;
+ while( <$in> ) {
+ print $out $_;
+ $rows++;
+ }
+
+ #trailer
+ my $trail = sprintf(
+ "%-6s%-4s%-27s%-6s%0.6d%-7s%0.9d%-9s%0.9d\n",
+ ' COMP:', 'VISP', '', ',SEQ:', $seq,
+ ',LINES:', $rows+2, ',LETTERS:', $rows,
+ );
+ warn "TRAILER: $trail" if $DEBUG;
+ print $out $trail;
+
+ close $in;
+ close $out;
+
+ my $zipfile = sprintf('%s_%0.6d.zip', $prefix, $seq);
+ my $command = "cd $dir; zip $zipfile $newfile";
+ warn "compressing to $zipfile\n$command\n" if $DEBUG;
+ system($command) and die "$command failed\n";
+
+ my $connection = $ftp_target->connect; # dies on error
+ $connection->put($zipfile);
+
+ my $template = join("\n",$conf->config('bridgestone-confirm_template'));
+ if ( $template ) {
+ my $tmpl_obj = Text::Template->new(
+ TYPE => 'STRING', SOURCE => $template
+ );
+ my $content = $tmpl_obj->fill_in( HASH =>
+ {
+ zipfile => $zipfile,
+ prefix => $prefix,
+ seq => $seq,
+ rows => $rows,
+ }
+ );
+ my ($head, $body) = split("\n\n", $content, 2);
+ $head =~ /^subject:\s*(.*)$/im;
+ my $subject = $1;
+
+ $head =~ /^to:\s*(.*)$/im;
+ my $to = $1;
+
+ send_email(
+ to => $to,
+ from => $conf->config('invoice_from', $agentnum),
+ subject => $subject,
+ body => $body,
+ );
+ } else { #!$template
+ warn "$me agent $agentnum has no bridgestone-confirm_template, no email sent\n";
+ }
+
+ $seq++;
+ warn "setting batch counter to $seq\n" if $DEBUG;
+ $conf->set('bridgestone-batch_counter', $seq, $agentnum);
+
+ } else { # not bridgestone
+
+ # this is the usual case
+
+ my $connection = $ftp_target->connect; # dies on error
+ $connection->put("$file-$date.csv");
+
}
- } #opt{format}
+
+ } #opt{handling}
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';