5 use Date::Format qw(time2str);
6 use File::Temp qw(tempdir);
7 use Net::SFTP::Foreign;
8 use FS::UID qw(adminsuidsetup);
9 use FS::Record qw(qsearch qsearchs);
15 getopts('va:P:C:T:', \%opt);
17 #$Net::SFTP::Foreign::debug = -1;
20 freeside-ipifony-download
26 freesideuser sftpuser@hostname[:path]
37 my $user = shift or die &HELP_MESSAGE;
48 die "no such directory: $opt{a}\n"
50 die "archive directory $opt{a} is not writable by the freeside user\n"
56 # find this category (don't auto-create it, it should exist already)
57 my $category = qsearchs('pkg_category', { categoryname => $opt{C} });
58 if (!defined($category)) {
59 die "Package category '$opt{C}' does not exist.\n";
61 $categorynum = $category->categorynum;
64 my $taxclass = $opt{T} || '';
66 #my $tmpdir = File::Temp->newdir();
67 my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere?
71 my ($sftpuser, $path);
73 $sftpuser = $1 || $ENV{USER};
78 if ( $opt{P} =~ /^(\d+)$/ ) {
82 # for now assume SFTP download as the only method
83 print STDERR "Connecting to $sftpuser\@$host...\n" if $opt{v};
85 my $sftp = Net::SFTP::Foreign->new(
89 # for now we don't support passwords. use authorized_keys.
91 more => ($opt{v} ? '-v' : ''),
93 die "failed to connect to '$sftpuser\@$host'\n(".$sftp->error.")\n"
96 $sftp->setcwd($path) if $path;
98 my $files = $sftp->ls('.', wanted => qr/\.csv$/, names_only => 1);
100 print STDERR "No charge files found.\n" if $opt{v};
103 FILE: foreach my $filename (@$files) {
104 print STDERR "Retrieving $filename\n" if $opt{v};
105 $sftp->get("$filename", "$tmpdir/$filename");
107 warn "failed to download $filename\n";
111 # make sure server archive dir exists
112 if ( !$sftp->stat('Archive') ) {
113 print STDERR "Creating $path/Archive\n" if $opt{v};
114 $sftp->mkdir('Archive');
116 # something is seriously wrong
117 die "failed to create archive directory on server:\n".$sftp->error."\n";
120 #move to server archive dir
121 $sftp->rename("$filename", "Archive/$filename");
123 warn "failed to archive $filename on server:\n".$sftp->error."\n";
124 } # process it anyway, I guess/
126 #copy to local archive dir
128 print STDERR "Copying $tmpdir/$filename to archive dir $opt{a}\n"
130 copy("$tmpdir/$filename", $opt{a});
131 warn "failed to copy $tmpdir/$filename to $opt{a}: $!" if $!;
134 open my $fh, "<$tmpdir/$filename";
136 if ($header !~ /^cust_id/) {
137 warn "warning: $filename has incorrect header row:\n$header\n";
140 my $csv = Text::CSV->new; # orthodox CSV
142 while (my $line = <$fh>) {
143 $csv->parse($line) or do {
144 warn "can't parse $filename: ".$csv->error_input."\n";
147 @hash{@fields} = $csv->fields();
148 my $cust_main = FS::cust_main->by_key($hash{custnum});
150 warn "customer #$hash{custnum} not found\n";
153 print STDERR "Found customer #$hash{custnum}: ".$cust_main->name."\n"
156 # construct arguments for $cust_main->charge
158 amount => $hash{amount},
159 quantity => $hash{quantity},
160 start_date => $cust_main->next_bill_date,
161 pkg => $hash{date_desc},
162 taxclass => $taxclass,
164 if (my $classname = $hash{classname}) {
165 if (!exists($classnum_of{$classname}) ) {
167 my $pkg_class = qsearchs('pkg_class', {
168 classname => $classname,
169 categorynum => $categorynum,
171 if (!defined($pkg_class)) {
173 $pkg_class = FS::pkg_class->new({
174 classname => $classname,
175 categorynum => $categorynum,
177 my $error = $pkg_class->insert;
178 die "Error creating package class for product code '$classname':\n".
183 $classnum_of{$classname} = $pkg_class->classnum;
185 $opt{classnum} = $classnum_of{$classname};
187 print STDERR " Charging $hash{amount}\n"
189 my $error = $cust_main->charge(\%opt);
191 warn "Error creating charge: $error" if $error;
195 $sum_charges += $hash{amount};
204 Processed files: @$files
205 Created charges: $num_charges
206 Sum of charges: \$".sprintf('%0.2f', $sum_charges)."
213 freeside-eftca-download - Retrieve payment batch responses from EFT Canada.
217 freeside-eftca-download [ -v ] [ -a archivedir ] user
221 Command line tool to download returned payment reports from the EFT Canada
222 gateway and void the returned payments. Uses the login and password from
223 'batchconfig-eft_canada'.
227 -a directory: Archive response files in the provided directory.
229 user: freeside username
233 You need to manually SFTP to ftp.eftcanada.com from the freeside account
234 and accept their key before running this script.