package FS::pay_batch::nacha;
use strict;
-use vars qw( %import_info %export_info $name $conf );
+use vars qw( %import_info %export_info $name $conf $entry_hash $DEBUG );
use Date::Format;
#use Time::Local 'timelocal';
#use FS::Conf;
$name = 'NACHA';
+my $i;
+$DEBUG = 0;
%import_info = (
#XXX stub finish me
my $origin = $1;
my $company = $conf->config('company_name', $pay_batch->agentnum);
- $company = substr($company. (' 'x23), 0, 23);
+
+ my $origin_name = $conf->config('batchconfig-nacha-origin_name')
+ || $company;
+ $origin_name = substr(uc($origin_name). (' 'x23), 0, 23);
+
+ $company = substr(uc($company). (' 'x16), 0, 16);
my $now = time;
#though they would probably want them numbered per company
my $batchnum = substr( ('0'x7). $pay_batch->batchnum, -7);
+ $entry_hash = 0;
+
+ warn "building File & Batch Header Records\n" if $DEBUG;
+
##
# File Header Record
##
'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)
+ $origin_name. #Immediate Origin Name / 23 char company name
+ $refcode. "\n". #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
+ $company. #on cust. statements
(' 'x20 ). #20 char "company internal use if desired"
$origin. #Company Identification (Immediate Origin)
'PPD'. #others?
(' 'x3). #Settlement Date / Reserved
'1'. #Originator Status Code
substr($dest, 0, 8). #Originating Financial Institution
- $batchnum #Batch Number ("number batches sequentially")
+ $batchnum. "\n" #Batch Number ("number batches sequentially")
},
my ($account, $aba) = split('@', $cust_pay_batch->payinfo);
+ $conf->config('batchconfig-nacha-destination') =~ /^\s*(\d{9})\s*$/
+ or die 'illegal NACHA Destination';
+ my $dest = $1;
+
+ # "Total of all positions 4-11 on each 6 record"
+ $entry_hash += substr($aba,0,8);
+
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);
+ #XXX paytype should actually be in the batch, but this will do for now
+ #27 checking debit, 37 savings debit
+ my $transaction_code = ( $cust_main->paytype =~ /savings/i ? '37' : '27' );
+ my $cust_name = substr($cust_main->name. (' 'x22), 0, 22);
+ $i++;
+ my $tracenum = $dest. substr(('0'x7). $i, -6);
#non-PPD transactions? future
+ warn "building PPD Record\n" if $DEBUG;
+
###
# PPD Entry Detail Record
###
'6'. #Record Type Code
- '27'. #27 checking debit, 37 savings debit XXX
+ $transaction_code. #Transaction Code
$aba. #Receiving DFI Identification, check digit
substr($account.(' 'x17), 0, 17). #DFI Account number (Left justify)
- sprintf('%010d', $cust_pay_batch->amount * 100). #Amount
+ sprintf('%010.0f', $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?)
+# (' 'x15). #15 digit "bank will assign trace number"
+ $tracenum.
+ "\n" # (00000?)
},
'footer' => sub {
my( $pay_batch, $batchcount, $batchtotal ) = @_;
+ #Only use the final 10 positions in the entry
+ $entry_hash = substr( '00'.$entry_hash, -10);
+
$conf->config('batchconfig-nacha-destination') =~ /^\s*(\d{9})\s*$/
or die 'illegal NACHA Destination';
my $dest = $1;
my $batchnum = substr( ('0'x7). $pay_batch->batchnum, -7);
+ my $lines = $batchcount + 4;
+ my $blocks = int($lines/10);
+ my $fill = '';
+
+ if ( my $remainder = $lines % 10 ) {
+ $blocks++;
+ $fill = ("\n".('9'x94))x( 10 - $remainder );
+ }
+
+ warn "building Batch & File Control Records\n" if $DEBUG;
+
###
# Batch Control Record
###
'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
+ $entry_hash.
+ sprintf('%012.0f', $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")
+ $batchnum. "\n". #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('%06d', $blocks). #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
+ $entry_hash.
+ sprintf('%012.0f', $batchtotal * 100). #Debit total
'000000000000'. #Credit total
- ( ' 'x39 ) #Reserved / blank
+ ( ' 'x39 ). #Reserved / blank
+
+ ###
+ # Pad with 9999 records to blocks of 10
+ ###
+
+ $fill
},