summaryrefslogtreecommitdiff
path: root/FS/FS/pay_batch
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2013-01-18 16:54:33 -0800
committerIvan Kohler <ivan@freeside.biz>2013-01-18 16:54:33 -0800
commit1fbe9c841ebb293b516dfa4d2611a5cd1a1cf5c5 (patch)
tree986774246cd919b0d353f1496463a3ae0f263e16 /FS/FS/pay_batch
parentc5fba52eb881e31ecc006224289885cde2cc96f3 (diff)
NACHA check batching, RT#20443
Diffstat (limited to 'FS/FS/pay_batch')
-rw-r--r--FS/FS/pay_batch/nacha.pm188
1 files changed, 188 insertions, 0 deletions
diff --git a/FS/FS/pay_batch/nacha.pm b/FS/FS/pay_batch/nacha.pm
new file mode 100644
index 0000000..999cd9e
--- /dev/null
+++ b/FS/FS/pay_batch/nacha.pm
@@ -0,0 +1,188 @@
+package FS::pay_batch::nacha;
+
+use strict;
+use vars qw( %import_info %export_info $name $conf );
+use Date::Format;
+#use Time::Local 'timelocal';
+#use FS::Conf;
+
+$name = 'NACHA';
+
+%import_info = (
+ #XXX stub finish me
+ 'filetype' => 'CSV',
+ 'fields' => [
+ ],
+ 'hook' => sub {
+ my $hash = shift;
+ },
+ 'approved' => sub { 1 },
+ 'declined' => sub { 0 },
+);
+
+%export_info = (
+
+ #optional
+ init => sub {
+ $conf = shift;
+ },
+
+ delimiter => '',
+
+
+ header => sub {
+ my( $pay_batch, $cust_pay_batch_arrayref ) = @_;
+
+ $conf->config('batchconfig-nacha-destination') =~ /^\s*(\d{9})\s*$/
+ or die 'illegal NACHA Destination';
+ my $dest = $1;
+
+ my $dest_name = $conf->config('batchconfig-nacha-destination_name');
+ $dest_name = substr( $dest_name. (' 'x23), 0, 23);
+
+ $conf->config('batchconfig-nacha-origin') =~ /^\s*(\d{10})\s*$/
+ or die 'illegal NACHA Origin';
+ my $origin = $1;
+
+ my $company = $conf->config('company_name', $pay_batch->agentnum);
+ $company = substr($company. (' 'x23), 0, 23);
+
+ my $now = time;
+
+ #haha don't want to break after a quarter million years of a batch a day
+ #or 54 years for 5000 agent-virtualized hosted companies batching daily
+ my $refcode = substr( (' 'x8). $pay_batch->batchnum, -8);
+
+ #or only 25,000 years or 5.4 for 5000 companies :)
+ #though they would probably want them numbered per company
+ my $batchnum = substr( ('0'x7). $pay_batch->batchnum, -7);
+
+ ##
+ # File Header Record
+ ##
+
+ '1'. #Record Type Code
+ '01'. #Priority Code
+ ' '. $dest. #Immediate Destination / 9-digit transit routing #
+ $origin. #Immediate Origin / 10 digit company number
+ time2str('%y%m%d', $now). #File Creation Date
+ time2str('%H%M', $now). #File Creation Time
+ 'A'. #XXX file ID modifier, mult. files in transit? [A-Z0-9]
+ '094'. #94 character records
+ '10'. #Blocking Factor
+ '1'. #Format code
+ $dest_name. #Immediate Destination Name / 23 char bank name
+ $company. #Immediate Origin Name / 23 char company name
+ $refcode. #Reference Code (internal/optional)
+
+ ###
+ # Batch Header Record
+ ###
+
+ '5'. #Record Type Code
+ '225'. #Service Class Code (220 credits only,
+ # 200 mixed debits & credits)
+ substr($company, 0, 16). #on cust. statements
+ (' 'x20 ). #20 char "company internal use if desired"
+ $origin. #Company Identification (Immediate Origin)
+ 'PPD'. #others?
+ #PPD "Prearranged Payments and Deposit entries" for consumer items
+ #CCD (Cash Concentration and Disbursement)
+ #CTX (Corporate Trade Exchange)
+ #TEL (Telephone initiated entires)
+ #WEB (Authorization received via the Internet)
+ 'InterntSvc'. #XXX from conf 10 char txn desc, printed on cust. statements
+
+ #6 char "Descriptive date" printed on customer statements
+ #XXX now? or use a separate post date?
+ time2str('%y%m%d', $now).
+
+ #6 char date transactions are to be posted
+ #XXX now? or do we need a future banking day date like eft_canada trainwreck
+ time2str('%y%m%d', $now).
+
+ (' 'x3). #Settlement Date / Reserved
+ '1'. #Originator Status Code
+ substr($dest, 0, 8). #Originating Financial Institution
+ $batchnum #Batch Number ("number batches sequentially")
+
+ },
+
+ 'row' => sub {
+ my( $cust_pay_batch, $pay_batch, $batchcount, $batchtotal ) = @_;
+
+ my ($account, $aba) = split('@', $cust_pay_batch->payinfo);
+
+ my $cust_main = $cust_pay_batch->cust_main;
+ my $cust_identifier = substr($cust_main->display_custnum. (' 'x15), 0, 15);
+
+ my $cust_name = substr($cust_main->name. (' 'x22), 0, 22);
+
+ #non-PPD transactions? future
+
+ ###
+ # PPD Entry Detail Record
+ ###
+
+ '6'. #Record Type Code
+ '27'. #27 checking debit, 37 savings debit XXX
+ $aba. #Receiving DFI Identification, check digit
+ substr($account.(' 'x17), 0, 17). #DFI Account number (Left justify)
+ sprintf('%010d', $cust_pay_batch->amount * 100). #Amount
+ $cust_identifier. #Individual Identification Number, 15 char
+ $cust_name. #Individual name (22-char)
+ ' '. #2 char "company internal use if desired"
+ '0'. #Addenda Record Indicator
+ (' 'x15) #15 digit "bank will assign trace number"
+ # (00000?)
+ },
+
+ 'footer' => sub {
+ my( $pay_batch, $batchcount, $batchtotal ) = @_;
+
+ $conf->config('batchconfig-nacha-destination') =~ /^\s*(\d{9})\s*$/
+ or die 'illegal NACHA Destination';
+ my $dest = $1;
+
+ $conf->config('batchconfig-nacha-origin') =~ /^\s*(\d{10})\s*$/
+ or die 'illegal NACHA Origin';
+ my $origin = $1;
+
+ my $batchnum = substr( ('0'x7). $pay_batch->batchnum, -7);
+
+ ###
+ # Batch Control Record
+ ###
+
+ '8'. #Record Type Code
+ '225'. #Service Class Code (220 credits only,
+ # 200 mixed debits&credits)
+ sprintf('%06d', $batchcount). #Entry / Addenda Count
+ '1234567890'. #XXX "Entry Hash" Total of all positions 4-11 on each 6 record. Only use the final 10 positions in the entry
+ sprintf('%012d', $batchtotal * 100). #Debit total
+ '000000000000'. #Credit total
+ $origin. #Company Identification (Immediate Origin)
+ (' 'x19). #Message Authentication Code (19 char blank)
+ (' 'x6). #Federal Reserve Use (6 char blank)
+ substr($dest, 0, 8). #Originating Financial Institution
+ $batchnum. #Batch Number ("number batches sequentially")
+
+ ###
+ # File Control Record
+ ###
+
+ '9'. #Record Type Code
+ '000001'. #Batch Counter (# of batch header recs)
+ sprintf('%06d', $batchcount + 4). #num of physical blocks on the file..?
+ sprintf('%08d', $batchcount). #total # of entry detail and addenda
+ '1234567890'. #XXX "Entry Hash" Total of all positions 4-11 on each 6 record. Only use the final 10 positions in the entry
+ sprintf('%012d', $batchtotal * 100). #Debit total
+ '000000000000'. #Credit total
+ ( ' 'x39 ) #Reserved / blank
+
+ },
+
+);
+
+1;
+