summaryrefslogtreecommitdiff
path: root/FS
diff options
context:
space:
mode:
authorChristopher Burger <burgerc@freeside.biz>2019-03-10 19:12:20 -0400
committerChristopher Burger <burgerc@freeside.biz>2019-03-10 19:12:20 -0400
commitb48c02a92562395c84dbfe8c47db5c4ba14891a0 (patch)
treeb2fda5bb8a2ed969b702e7006be988e47ee920a5 /FS
parent765aac1902113738afd1bcaee8eb25b44ee92e63 (diff)
RT# 82988 - Fixed so only formats that can handle electronic refunds can download those files
Diffstat (limited to 'FS')
-rw-r--r--FS/FS/Cron/pay_batch.pm2
-rw-r--r--FS/FS/Schema.pm1
-rw-r--r--FS/FS/cust_main/Billing_Batch.pm5
-rw-r--r--FS/FS/pay_batch.pm133
-rw-r--r--FS/FS/pay_batch/RBC.pm11
-rwxr-xr-xFS/bin/freeside-eftca-upload6
-rwxr-xr-xFS/bin/freeside-paymentech-upload1
-rwxr-xr-xFS/bin/freeside-rbc-upload1
8 files changed, 154 insertions, 6 deletions
diff --git a/FS/FS/Cron/pay_batch.pm b/FS/FS/Cron/pay_batch.pm
index 1e110f2..18532ac 100644
--- a/FS/FS/Cron/pay_batch.pm
+++ b/FS/FS/Cron/pay_batch.pm
@@ -67,7 +67,7 @@ sub pay_batch_submit {
my ($gateway, $payby, $agentnum) = @$config;
if ( $gateway->batch_processor->can('default_transport') ) {
- my $search = { status => 'O', payby => $payby };
+ my $search = { status => 'O', payby => $payby, type => 'DEBIT' };
$search->{agentnum} = $agentnum if $agentnum;
foreach my $pay_batch ( qsearch('pay_batch', $search) ) {
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index fc22d6c..8cc8416 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -2711,6 +2711,7 @@ sub tables_hashref {
'upload', @date_type, '', '',
'title', 'varchar', 'NULL',255, '', '',
'processor_id', 'varchar', 'NULL',255, '', '',
+ 'type', 'char', '', 6, 'DEBIT', '', # DEBIT/CREDIT
],
'primary_key' => 'batchnum',
'unique' => [],
diff --git a/FS/FS/cust_main/Billing_Batch.pm b/FS/FS/cust_main/Billing_Batch.pm
index 0e713e9..c1bb35f 100644
--- a/FS/FS/cust_main/Billing_Batch.pm
+++ b/FS/FS/cust_main/Billing_Batch.pm
@@ -83,6 +83,10 @@ sub batch_card {
);
}
+ my $paycode= $options{paycode} || '';
+ my $batch_type = "DEBIT";
+ $batch_type = "CREDIT" if $paycode eq 'C';
+
my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
@@ -95,6 +99,7 @@ sub batch_card {
my %pay_batch = (
'status' => 'O',
'payby' => FS::payby->payby2payment($payby),
+ 'type' => $batch_type,
);
$pay_batch{agentnum} = $self->agentnum if $conf->exists('batch-spoolagent');
diff --git a/FS/FS/pay_batch.pm b/FS/FS/pay_batch.pm
index 4aeb331..e8ae6ec 100644
--- a/FS/FS/pay_batch.pm
+++ b/FS/FS/pay_batch.pm
@@ -56,6 +56,10 @@ from FS::Record. The following fields are currently supported:
=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.
@@ -1154,7 +1158,136 @@ sub manual_approve {
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";
+
+ my @batch_refunds = qsearch({
+ 'table' => 'cust_pay_batch',
+ 'select' => 'cust_pay_batch.*',
+ 'extra_sql' => $extrasql,
+ });
+
+ warn "found ".scalar @batch_refunds." batch refunds.\n";
+ warn "Searching for their cust refunds...\n" if (scalar @batch_refunds > 0);
+ my ($delete_cust_refund_error, $delete_cust_pay_batch_error);
+
+ ## find the cust_pay_refund for all those
+ foreach (@batch_refunds) {
+ my $extra_batch_refund_sql = " WHERE custnum = '".$_->{Hash}->{custnum}."' AND refund = '".$_->{Hash}->{amount}."' ORDER BY _date DESC LIMIT 1";
+ my $cust_refund = qsearchs({
+ 'table' => 'cust_refund',
+ 'extra_sql' => $extra_batch_refund_sql,
+ });
+
+ warn "found cust refund number ".$cust_refund->{Hash}->{refundnum}.", now to delete it.\n" if $cust_refund;
+
+ ## delete the cust_pay_refund
+ $delete_cust_refund_error = $cust_refund->delete if $cust_refund;
+ warn "could not delete cust refund $delete_cust_refund_error\n" if $delete_cust_refund_error;
+
+ ## delete the refund from the batch.
+ unless ($delete_cust_refund_error) {
+ $delete_cust_pay_batch_error = $_->unbatch_and_delete;
+ warn "could not delete cust refund $delete_cust_pay_batch_error\n" if $delete_cust_pay_batch_error;
+ }
+
+ if ($delete_cust_refund_error || $delete_cust_pay_batch_error) { die "Could no delete cust_pay_batch refund\n"; }
+ else { warn "cust refund ".$cust_refund->{Hash}->{refundnum}." deleted\n"; }
+ }
+
+ FS::upgrade_journal->set_done('removed_refunds_nodownload_format');
+ }
+
# Set up configuration for gateways that have a Business::BatchPayment
# module.
diff --git a/FS/FS/pay_batch/RBC.pm b/FS/FS/pay_batch/RBC.pm
index 22521e0..7c165a3 100644
--- a/FS/FS/pay_batch/RBC.pm
+++ b/FS/FS/pay_batch/RBC.pm
@@ -154,7 +154,8 @@ $name = 'RBC';
my $pay_batch = shift;
my $mode = $testmode ? 'TEST' : 'PROD';
my $filenum = $testmode ? 'TEST' : sprintf("%04u", $pay_batch->batchnum);
- '$$AAPASTD0152['.$mode.'[NL$$'."\n".
+ my $qualifier = $pay_batch->type eq 'CREDIT' ? 'D' : 'A';
+ '$$AAP'.$qualifier.'STD0152['.$mode.'[NL$$'."\n".
'000001'.
'A'.
'HDR'.
@@ -219,13 +220,15 @@ $name = 'RBC';
},
footer => sub {
my ($pay_batch, $batchcount, $batchtotal) = @_;
+
+ my $batch_info = '0' x 20 . sprintf("%06u", $batchcount) . sprintf("%014.0f", $batchtotal*100);
+ $batch_info = sprintf("%06u", $batchcount) . sprintf("%014.0f", $batchtotal*100) . '0' x 20 if ($pay_batch->type eq 'CREDIT');
+
sprintf("%06u", $i + 1).
'Z'.
'TRL'.
sprintf("%10s", $client_num).
- '0' x 20 .
- sprintf("%06u", $batchcount).
- sprintf("%014.0f", $batchtotal*100).
+ $batch_info.
'00' .
'000000' . # total number of customer information records
' ' x 84
diff --git a/FS/bin/freeside-eftca-upload b/FS/bin/freeside-eftca-upload
index 503c7a3..18656c9 100755
--- a/FS/bin/freeside-eftca-upload
+++ b/FS/bin/freeside-eftca-upload
@@ -32,8 +32,12 @@ my @batches;
if($opt_a) {
local $@;
+
+ my %criteria= ( 'status' => 'O', 'payby' => 'CHEK' );
+ $criteria{'type'} = 'DEBIT' unless FS::pay_batch->can_handle_electronic_refunds('eft_canada');
+
eval {
- @batches = qsearch('pay_batch', { 'status' => 'O', 'payby' => 'CHEK' })
+ @batches = qsearch('pay_batch', \%criteria)
};
log_error_and_die ("Fatal database error: $@")
if $@;
diff --git a/FS/bin/freeside-paymentech-upload b/FS/bin/freeside-paymentech-upload
index d6ca0cd..8ec8a5d 100755
--- a/FS/bin/freeside-paymentech-upload
+++ b/FS/bin/freeside-paymentech-upload
@@ -41,6 +41,7 @@ my @batches;
if($opt_a) {
my %criteria = (status => 'O');
$criteria{'payby'} = uc($opt_p) if $opt_p;
+ $criteria{'type'} = 'DEBIT' unless FS::pay_batch->can_handle_electronic_refunds('paymentech');
@batches = qsearch('pay_batch', \%criteria);
log_and_die("No open batches found".($opt_p ? " of type '$opt_p'" : '').".\n")
if !@batches;
diff --git a/FS/bin/freeside-rbc-upload b/FS/bin/freeside-rbc-upload
index 3fff32a..8f67a6e 100755
--- a/FS/bin/freeside-rbc-upload
+++ b/FS/bin/freeside-rbc-upload
@@ -33,6 +33,7 @@ my @batches;
if($opt_a) {
my %criteria = (status => 'O');
$criteria{'payby'} = uc($opt_p) if $opt_p;
+ $criteria{'type'} = 'DEBIT' unless FS::pay_batch->can_handle_electronic_refunds('RBC');
@batches = qsearch('pay_batch', \%criteria);
die "No open batches found".($opt_p ? " of type '$opt_p'" : '').".\n"
if !@batches;