use Time::Local;
use Text::CSV_XS;
use Date::Parse qw(str2time);
-use Business::CreditCard qw(cardtype);
+use Business::CreditCard qw( 0.35 cardtype );
use FS::Record qw( dbh qsearch qsearchs );
use FS::Conf;
use FS::cust_pay;
use FS::Log;
+use Try::Tiny;
=head1 NAME
=item title - unique batch identifier
+=item processor_id -
+
+=item type - batch type payents (DEBIT), or refunds (CREDIT)
+
For incoming batches, the combination of 'title', 'payby', and 'agentnum'
must be unique.
return '';
}
- my $batch = Business::BatchPayment->create(Batch =>
- batch_id => $self->batchnum,
- items => \@items
- );
- $processor->submit($batch);
+ try {
+ my $batch = Business::BatchPayment->create(Batch =>
+ batch_id => $self->batchnum,
+ items => \@items
+ );
+ $processor->submit($batch);
- if ($batch->processor_id) {
- $self->set('processor_id',$batch->processor_id);
- $self->replace;
- }
+ if ($batch->processor_id) {
+ $self->set('processor_id',$batch->processor_id);
+ $self->replace;
+ }
+ } catch {
+ $dbh->rollback if $oldAutoCommit;
+ die $_;
+ };
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
return;
}
+=item batch_download_formats
+
+returns a hash of batch download formats.
+
+my %download_formats = FS::pay_batch::batch_download_formats;
+
+=cut
+
+sub batch_download_formats {
+
+ my @formats = (
+ '' =>
+ 'Default batch mode',
+ 'NACHA' =>
+ '94 byte NACHA',
+ 'csv-td_canada_trust-merchant_pc_batch' =>
+ 'CSV file for TD Canada Trust Merchant PC Batch',
+ 'csv-chase_canada-E-xactBatch' =>
+ 'CSV file for Chase Canada E-xactBatch',
+ 'PAP' =>
+ '80 byte file for TD Canada Trust PAP Batch',
+ 'BoM' =>
+ 'Bank of Montreal ECA batch',
+ 'ach-spiritone' =>
+ 'Spiritone ACH batch',
+ 'paymentech' =>
+ 'XML file for Chase Paymentech',
+ 'RBC' =>
+ 'Royal Bank of Canada PDS batch',
+ 'td_eft1464' =>
+ '1464 byte file for TD Commercial Banking EFT',
+ 'eft_canada' =>
+ 'EFT Canada CSV batch',
+ 'CIBC' =>
+ '80 byte file for Canadian Imperial Bank of Commerce',
+ # insert new batch formats here
+ );
+
+}
+
+=item batch_download_formats
+
+returns a hash of batch download formats.
+
+my %download_formats = FS::pay_batch::batch_download_formats;
+
+=cut
+
+sub can_handle_electronic_refunds {
+
+ my $self = shift;
+ my $format = shift;
+ my $conf = new FS::Conf;
+
+ tie my %download_formats, 'Tie::IxHash', batch_download_formats;
+
+ my %paybatch_mods = (
+ 'NACHA' => 'nacha',
+ 'csv-td_canada_trust-merchant_pc_batch' => 'td_canada_trust',
+ 'csv-chase_canada-E-xactBatch' => 'chase-canada',
+ 'PAP' => 'PAP',
+ 'BoM' => 'BoM',
+ 'ach-spiritone' => 'ach_spiritone',
+ 'paymentech' => 'paymentech',
+ 'RBC' => 'RBC',
+ 'td_eft1464' => 'td_eft1464',
+ 'eft_canada' => 'eft_canada',
+ 'CIBC' => 'CIBC',
+ );
+
+ %download_formats = ( $format => $download_formats{$format}, ) if $format;
+
+ foreach my $key (keys %download_formats) {
+ my $mod = "FS::pay_batch::".$paybatch_mods{$key};
+ if ($mod->can('can_handle_credits')) {
+ return '1' if $conf->exists('batchconfig-'.$key);
+ }
+ }
+
+ return;
+
+}
+
+use FS::upgrade_journal;
sub _upgrade_data {
+
+ # check if there are any pending batch refunds and no download format configured
+ # that allows electronic refunds.
+ unless ( FS::upgrade_journal->is_done('removed_refunds_nodownload_format') ) {
+
+ ## get a list of all refunds in batches.
+ my $extrasql = " LEFT JOIN pay_batch USING ( batchnum ) WHERE cust_pay_batch.paycode = 'C' AND pay_batch.download IS NULL AND pay_batch.type = 'DEBIT' ";
+
+ my @batch_refunds = qsearch({
+ 'table' => 'cust_pay_batch',
+ 'select' => 'cust_pay_batch.*',
+ 'extra_sql' => $extrasql,
+ });
+
+ my $replace_error;
+
+ if (@batch_refunds) {
+ warn "found ".scalar @batch_refunds." batch refunds.\n";
+ warn "Searching for their cust refunds...\n" if (scalar @batch_refunds > 0);
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ ## move refund to credit batch.
+ foreach my $cust_pay_batch (@batch_refunds) {
+ my $payby = $cust_pay_batch->payby eq "CARD" ? "CARD" : "CHEK";
+
+ my %pay_batch = (
+ 'status' => 'O',
+ 'payby' => $payby,
+ 'type' => 'CREDIT',
+ );
+
+ my $pay_batch = qsearchs( 'pay_batch', \%pay_batch );
+
+ unless ( $pay_batch ) {
+ $pay_batch = new FS::pay_batch \%pay_batch;
+ my $error = $pay_batch->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ warn "error creating a $payby credit batch: $error\n";
+ }
+ }
+
+ $cust_pay_batch->batchnum($pay_batch->batchnum);
+ $replace_error = $cust_pay_batch->replace();
+ if ( $replace_error ) {
+ $dbh->rollback if $oldAutoCommit;
+ warn "Unable to move credit to a credit batch: $replace_error";
+ }
+ else {
+ warn "Moved cust pay credit ".$cust_pay_batch->paybatchnum." to ".$cust_pay_batch->payby." credit batch ".$cust_pay_batch->batchnum."\n";
+ }
+ }
+ } #end @batch_refunds
+ else { warn "No batch refunds found\n"; }
+
+ FS::upgrade_journal->set_done('removed_refunds_nodownload_format') unless $replace_error;
+ }
+
# Set up configuration for gateways that have a Business::BatchPayment
# module.