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:', \%opt);
17 #$Net::SFTP::Foreign::debug = -1;
20 freeside-ipifony-download
25 freesideuser sftpuser@hostname[:path]
36 my $user = shift or die &HELP_MESSAGE;
47 die "no such directory: $opt{a}\n"
49 die "archive directory $opt{a} is not writable by the freeside user\n"
55 # find this category (don't auto-create it, it should exist already)
56 my $category = qsearchs('pkg_category', { categoryname => $opt{C} });
57 if (!defined($category)) {
58 die "Package category '$opt{C}' does not exist.\n";
60 $categorynum = $category->categorynum;
63 #my $tmpdir = File::Temp->newdir();
64 my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere?
68 my ($sftpuser, $path);
70 $sftpuser = $1 || $ENV{USER};
75 if ( $opt{P} =~ /^(\d+)$/ ) {
79 # for now assume SFTP download as the only method
80 print STDERR "Connecting to $sftpuser\@$host...\n" if $opt{v};
82 my $sftp = Net::SFTP::Foreign->new(
86 # for now we don't support passwords. use authorized_keys.
88 more => ($opt{v} ? '-v' : ''),
90 die "failed to connect to '$sftpuser\@$host'\n(".$sftp->error.")\n"
93 $sftp->setcwd($path) if $path;
95 my $files = $sftp->ls('.', wanted => qr/\.csv$/, names_only => 1);
97 print STDERR "No charge files found.\n" if $opt{v};
100 FILE: foreach my $filename (@$files) {
101 print STDERR "Retrieving $filename\n" if $opt{v};
102 $sftp->get("$filename", "$tmpdir/$filename");
104 warn "failed to download $filename\n";
108 # make sure server archive dir exists
109 if ( !$sftp->stat('Archive') ) {
110 print STDERR "Creating $path/Archive\n" if $opt{v};
111 $sftp->mkdir('Archive');
113 # something is seriously wrong
114 die "failed to create archive directory on server:\n".$sftp->error."\n";
117 #move to server archive dir
118 $sftp->rename("$filename", "Archive/$filename");
120 warn "failed to archive $filename on server:\n".$sftp->error."\n";
121 } # process it anyway, I guess/
123 #copy to local archive dir
125 print STDERR "Copying $tmpdir/$filename to archive dir $opt{a}\n"
127 copy("$tmpdir/$filename", $opt{a});
128 warn "failed to copy $tmpdir/$filename to $opt{a}: $!" if $!;
131 open my $fh, "<$tmpdir/$filename";
133 if ($header !~ /^cust_id/) {
134 warn "warning: $filename has incorrect header row:\n$header\n";
137 my $csv = Text::CSV->new; # orthodox CSV
139 while (my $line = <$fh>) {
140 $csv->parse($line) or do {
141 warn "can't parse $filename: ".$csv->error_input."\n";
144 @hash{@fields} = $csv->fields();
145 my $cust_main = FS::cust_main->by_key($hash{custnum});
147 warn "customer #$hash{custnum} not found\n";
150 print STDERR "Found customer #$hash{custnum}: ".$cust_main->name."\n"
153 # construct arguments for $cust_main->charge
155 amount => $hash{amount},
156 quantity => $hash{quantity},
157 start_date => $cust_main->next_bill_date,
158 pkg => $hash{date_desc},
160 if (my $classname = $hash{classname}) {
161 if (!exists($classnum_of{$classname}) ) {
163 my $pkg_class = qsearchs('pkg_class', {
164 classname => $classname,
165 categorynum => $categorynum,
167 if (!defined($pkg_class)) {
169 $pkg_class = FS::pkg_class->new({
170 classname => $classname,
171 categorynum => $categorynum,
173 my $error = $pkg_class->insert;
174 die "Error creating package class for product code '$classname':\n".
179 $classnum_of{$classname} = $pkg_class->classnum;
181 $opt{classnum} = $classnum_of{$classname};
183 # XXX what's the tax status of these charges?
184 print STDERR " Charging $hash{amount}\n"
186 my $error = $cust_main->charge(\%opt);
188 warn "Error creating charge: $error" if $error;
192 $sum_charges += $hash{amount};
201 Processed files: @$files
202 Created charges: $num_charges
203 Sum of charges: \$".sprintf('%0.2f', $sum_charges)."
210 freeside-eftca-download - Retrieve payment batch responses from EFT Canada.
214 freeside-eftca-download [ -v ] [ -a archivedir ] user
218 Command line tool to download returned payment reports from the EFT Canada
219 gateway and void the returned payments. Uses the login and password from
220 'batchconfig-eft_canada'.
224 -a directory: Archive response files in the provided directory.
226 user: freeside username
230 You need to manually SFTP to ftp.eftcanada.com from the freeside account
231 and accept their key before running this script.