diff options
author | Mark Wells <mark@freeside.biz> | 2012-06-13 16:18:49 -0700 |
---|---|---|
committer | Mark Wells <mark@freeside.biz> | 2012-06-13 16:18:49 -0700 |
commit | 9ef78be87df0f0f880ff5d903ed6243b67369cf0 (patch) | |
tree | e69278b1e33baf2b9c0356ed31435fc0f0188b01 /FS/FS/Cron | |
parent | daa09251fec52517b630b3f6935041dc7c795f90 (diff) |
table of FTP targets for invoice spool upload, #17620
Diffstat (limited to 'FS/FS/Cron')
-rw-r--r-- | FS/FS/Cron/upload.pm | 290 |
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; ''; |