summaryrefslogtreecommitdiff
path: root/FS/FS/pay_batch
diff options
context:
space:
mode:
authormark <mark>2010-11-12 23:33:53 +0000
committermark <mark>2010-11-12 23:33:53 +0000
commit5188e8406a1fa2bee63ea81090ffefe3d4bf1b89 (patch)
treea1e17929eaca5e3c5ee73a6ef355365b3f26c4ec /FS/FS/pay_batch
parent718210a60786d78e33031ab60a7614bd009b4851 (diff)
TD EFT batch format, RT#10545
Diffstat (limited to 'FS/FS/pay_batch')
-rw-r--r--FS/FS/pay_batch/td_eft1464.pm229
1 files changed, 229 insertions, 0 deletions
diff --git a/FS/FS/pay_batch/td_eft1464.pm b/FS/FS/pay_batch/td_eft1464.pm
new file mode 100644
index 000000000..1fbf2ade2
--- /dev/null
+++ b/FS/FS/pay_batch/td_eft1464.pm
@@ -0,0 +1,229 @@
+package FS::pay_batch::td_eft1464;
+
+use strict;
+use vars qw(@ISA %import_info %export_info $name);
+use Date::Format 'time2str';
+use FS::Conf;
+use FS::Record qw(qsearch);
+
+=head1 NAME
+
+td_eft1464 - TD Commercial Banking EFT1464 format
+
+=head1 CONFIGURATION
+
+The Freeside option 'batchconfig-td_eft1464' must be set
+with the following values on separate lines:
+
+=over 4
+
+=item Originator ID
+
+=item TD Datacenter Location
+
+00400 - Vancouver
+00410 - Montreal
+00420 - Toronto
+00430 - Halifax
+00470 - Winnipeg
+00490 - Calgary
+
+=item Short Name
+
+=item Long Name
+
+=item Returned Payment Branch (5 digits)
+
+=item Returned Payment Account
+
+=item Transaction Type Code - defaults to "437" (Internet access)
+
+=back
+
+=cut
+
+my $conf;
+my %opt;
+my $i;
+
+$name = 'td_eft1464';
+# TD Bank EFT 1464 Byte format
+
+%import_info = (
+ 'filetype' => 'variable',
+ 'parse' => \&parse,
+ 'fields' => [ qw(
+ status
+ paid
+ paybatchnum
+ ) ],
+ 'hook' => sub {
+ my $hash = shift;
+ $hash->{'_date'} = time;
+ $hash->{'paid'} = sprintf('%.2f', $hash->{'paid'});
+ },
+ 'approved' => sub {
+ my $hash = shift;
+ $hash->{'status'} eq 'A'
+ },
+ 'declined' => sub {
+ my $hash = shift;
+ $hash->{'status'} eq 'D';
+ },
+ 'begin_condition' => sub {
+ my $hash = shift;
+ $hash->{'status'} eq 'A' or $hash->{'status'} eq 'D';
+ },
+ 'end_condition' => sub {
+ my $hash = shift;
+ $hash->{'status'} eq 'END'
+ },
+ 'close_condition' => sub {
+ my $batch = shift;
+ my @cust_pay_batch = qsearch('cust_pay_batch',
+ { batchnum => $batch->batchnum }
+ );
+ return ( (grep {! length($_->status) } @cust_pay_batch) == 0 );
+ },
+);
+
+sub parse {
+ my ($batch, $line) = @_;
+ $batch->setfield('import_state','') if !$batch->import_state;
+ return 'END' if $batch->import_state eq 'END';
+ if( $batch->import_state eq '212' ) {
+ # APX212 fields:
+ # trace number, trans type, amount, due date, routing number,
+ # account number, xref number, return routing number and account
+ # The only ones we take are amount and xref number.
+ if( $line =~ /CREDITS\s+DEBITS/ ) {
+ $batch->setfield('import_state', 'END');
+ return 'END';
+ }
+ $line =~ /^\d{22} D\d{3} (.{14}) \d{5} \d{4}-\d{5} .{12} (.{19}).*$/
+ or die "can't parse: $line";
+ # strip leading zeroes/spaces from paybatchnum at this point
+ return ('A', $1, sprintf('%u',$2));
+ }
+ elsif( $batch->import_state eq '234' ) {
+ # APX234 fields:
+ # payor name, xref number, due date, routing number, account number,
+ # amount, reason for return
+ if( $line =~ /TOTAL NUMBER -/ ) {
+ $batch->setfield('import_state', 'END');
+ return 'END';
+ }
+ $line =~ /^.{22} (.{19}) \d\d\/\d\d\/\d\d \d{9} .{12} (.{14}).*$/
+ or die "can't parse: $line";
+ return ('D', $2, sprintf('%u',$1));
+ }
+ else {
+ if ( $line =~ /ITEM TRACE NUMBER/ ) {
+ $batch->setfield('import_state','212');
+ }
+ elsif ( $line =~ /REASON FOR RETURN/ ) {
+ $batch->setfield('import_state','234');
+ } # else leave it undefined
+ return 'HEADER';
+ }
+}
+
+%export_info = (
+ init => sub {
+ $conf = shift;
+ @opt{
+ 'origid',
+ 'datacenter',
+ 'shortname',
+ 'longname',
+ 'retbranch',
+ 'retacct',
+ 'cpacode',
+ } = $conf->config("batchconfig-td_eft1464");
+ $opt{'origid'} = sprintf('%-10s', $opt{'origid'});
+ $opt{'shortname'} = sprintf('%-15s', $opt{'shortname'});
+ $opt{'longname'} = sprintf('%-30s', $opt{'longname'});
+ $opt{'retbranch'} = '0004'.sprintf('%5s',$opt{'retbranch'});
+ $opt{'retacct'} = sprintf('%-11s', $opt{'retacct'}). ' ';
+ $i = 1;
+ },
+ header => sub {
+ my $pay_batch = shift;
+ my @cust_pay_batch = @{(shift)};
+ my $time = $pay_batch->download || time;
+ my $now = sprintf("%03u%03u",
+ (localtime(time))[5],#year since 1900
+ (localtime(time))[7]+1);#day of year
+
+ # Request settlement the next day
+ my $duedate = time+86400;
+ $opt{'due'} = sprintf("%03u%03u",
+ (localtime($duedate))[5],
+ (localtime($duedate))[7]+1);
+
+ $opt{'fcn'} =
+ sprintf('%04u', ($pay_batch->batchnum % 9999)+1), # file creation number
+ join('',
+ 'A', #record type
+ sprintf('%09u', 1), #record number
+ $opt{'origid'},
+ $opt{'fcn'},
+ $now,
+ $opt{'datacenter'},
+ ' ' x 1429 #filler
+ );
+ },
+ row => sub {
+ my ($cust_pay_batch, $pay_batch) = @_;
+ my ($account, $aba) = split('@', $cust_pay_batch->payinfo);
+ $i++;
+ # The 1464 byte format supports up to 5 payments per line,
+ # but we're only going to send 1.
+ my $control = join('',
+ 'D', # for 'debit'
+ sprintf("%09u", $i), #record number
+ $opt{'origid'},
+ $opt{'fcn'},
+ );
+ my $payment = join('',
+ $opt{'cpacode'} || 437, # CPA code, defaults to "Internet access"
+ sprintf('%010.0f', $cust_pay_batch->amount*100),
+ $opt{'due'}, #due date...? XXX
+ sprintf('%09u', $aba),
+ sprintf('%-12s', $account),
+ ' ' x 22,
+ ' ' x 3,
+ $opt{'shortname'},
+ sprintf('%-30s',
+ join(' ',
+ $cust_pay_batch->first, $cust_pay_batch->last)
+ ),
+ $opt{'longname'},
+ $opt{'origid'},
+ sprintf('%-19s', $cust_pay_batch->paybatchnum), # originator reference num
+ $opt{'retbranch'},
+ $opt{'retacct'},
+ ' ' x 22,
+ ' ' x 2,
+ '0' x 11,
+ );
+ return $control . $payment . (' ' x 720);
+ },
+ footer => sub {
+ my ($pay_batch, $batchcount, $batchtotal) = @_;
+ join('',
+ 'Z',
+ sprintf('%09u', $batchcount + 2),
+ $opt{'origid'},
+ $opt{'fcn'},
+ sprintf('%014.0f', $batchtotal*100), # total of debit txns
+ sprintf('%08u', $batchcount), # number of debit txns
+ '0' x 14, # total of credit txns
+ '0' x 8, # total of credit txns
+ ' ' x 1396,
+ )
+ },
+);
+
+1;
+