#!/usr/bin/perl use strict; use Getopt::Std; use Date::Format; use Net::SFTP::Foreign::Compat; use FS::UID qw(adminsuidsetup datasrc); use FS::cdr; ### So much false laziness with freeside-cdr-sftp_and_import ### but vocus needs special handling to choose which files to load ### # parse command line ### use vars qw( $opt_r $opt_d $opt_v $opt_s ); getopts('r:d:vs'); my $user = shift or die &usage; adminsuidsetup $user; # %%%FREESIDE_CACHE%%% my $cachedir = '%%%FREESIDE_CACHE%%%/cache.'. datasrc. '/cdrs'; mkdir $cachedir unless -d $cachedir; use vars qw( $servername ); $servername = shift or die &usage; ### # get the file list ### warn "Retrieving directory listing\n" if $opt_v; my $ls; my $ls_sftp = sftp(); $ls_sftp->setcwd($opt_r) or die "can't chdir to $opt_r\n" if $opt_r; $ls = $ls_sftp->ls('.', wanted => qr/^VAP.*\.csv\.gz$/i, names_only => 1 ); ### # vocus-specific part -- only use highest-numbered file for day ### my %dates; foreach my $filename ( @$ls ) { my ($filepre,$filedate,$iter) = $filename =~ /^(VAP\d+\-)(\d{4}\-\d{2}\-\d{2})(\.\d+)?.csv.gz$/; unless ($filepre && $filedate) { die "unparsable filename $filename"; #no warn and skip, might process wrong file for date } $iter =~ s/\.// if length($iter); #not clear if same day can have different initial digits after VAP, # stated rule is "use the highest-numbered file for a given day", # so using date as key, but die if iter can't resolve conflict if (!$dates{$filedate}) { $dates{$filedate} = {}; } elsif ($dates{$filedate}{'iter'} eq $iter) { die "duplicate iterators found for $filedate\n" } $dates{$filedate}{'files'} ||= []; push @{$dates{$filedate}{'files'}}, $filename; # don't actually expect iter of 0, but just in case, 0 trumps undef if (!defined($dates{$filedate}{'iter'}) or (($iter || 0) > $dates{$filedate}{'iter'})) { $dates{$filedate}{'iter'} = $iter; $dates{$filedate}{'pre'} = $filepre; } } ### # import each file ### foreach my $filedate ( keys %dates ) { my $filename = $dates{$filedate}{'pre'} . $filedate; $filename .= '.'.$dates{$filedate}{'iter'} if defined($dates{$filedate}{'iter'}); $filename .= '.csv.gz'; warn "Downloading $filename\n" if $opt_v; #get the file my $sftp = sftp(); $sftp->get($filename, "$cachedir/$filename") or do { unlink "$cachedir/$filename"; my $error = "Can't get $filename: ". $sftp->error . "\n"; if ( $opt_s ) { warn $error; next; } else { die $error; } }; warn "Processing $filename\n" if $opt_v; my $ungziped = $filename; $ungziped =~ s/\.gz$//; if(system('gunzip', "$cachedir/$filename") != 0) { unlink "$cachedir/$filename"; my $error = "gunzip of '$cachedir/$filename' failed\n"; if ( $opt_s ) { warn $error; next; } else { die $error; } } my $import_options = { 'file' => "$cachedir/$ungziped", 'format' => 'vocus', 'batch_namevalue' => 'vocus-'.$filedate, #should further ensure only one file per date # 'empty_ok' => 1, }; my $error = FS::cdr::batch_import($import_options); if ( $error ) { unlink "$cachedir/$filename"; unlink "$cachedir/$ungziped"; $error = "Error importing $ungziped: $error\n"; if ( $opt_s ) { warn $error; next; } else { die $error; } } else { if ( $opt_d ) { my $timestamp = time2str('%Y-%m-%d', time); my $sftp = sftp(); foreach my $mfilename (@{$dates{$filedate}{'files'}}) { warn "Moving $mfilename\n" if $opt_v; $sftp->rename($mfilename, "$opt_d/$mfilename-$timestamp") or do { unlink "$cachedir/$filename"; unlink "$cachedir/$ungziped"; $error = "$mfilename imported, but can't move to $opt_d: ". $sftp->error . "\n"; if ( $opt_s ) { warn $error; next; } else { die $error; } }; } } } unlink "$cachedir/$filename"; unlink "$cachedir/$ungziped"; } ### # subs ### sub usage { "Usage: freeside-cdr-vocus [ -r remotefolder ] [ -d donefolder ] [ -v level ] [ -s ] user [sftpuser@]servername "; } use vars qw( $sftp ); sub sftp { #reuse connections return $sftp if $sftp && $sftp->cwd; my %sftp = ( host => $servername ); $sftp = Net::SFTP::Foreign->new(%sftp); $sftp->error and die "SFTP connection failed: ". $sftp->error; $sftp; } =head1 NAME freeside-cdr-vocus - Download Vocus CDR files =head1 SYNOPSIS freeside-cdr-vocus [ -r remotefolder ] [ -d donefolder ] [ -v level ] [ -s ] user [sftpuser@]servername =head1 DESCRIPTION Command line tool to download Vocus CDR files from a remote server via SFTP and then import them into the database. CDR tarrif types need to be configured as CDR types in freeside. If multiple files for a given day are found, the one with the highest iterator will be used (though upon successful import, all existing files for the day will be moved by the -d option.) -r: if specified, changes into this remote folder before starting -d: if specified, moves files to the specified folder when done -v: verbose -s: Warn and skip files which could not be imported rather than abort user: freeside username [sftpuser@]servername: remote server =head1 BUGS =head1 SEE ALSO L =cut 1;