Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
ACH Format code
Message
From
12/02/2014 01:07:49
 
 
To
11/02/2014 15:47:19
General information
Forum:
Visual FoxPro
Category:
Coding, syntax & commands
Title:
Environment versions
Visual FoxPro:
VFP 9 SP2
OS:
Windows Server 2012
Network:
Windows 2008 Server
Database:
MS SQL Server
Application:
Web
Miscellaneous
Thread ID:
01594091
Message ID:
01594114
Views:
64
This message has been marked as the solution to the initial question of the thread.
Likes (1)
I do indeed. The most popular ACH format is called NACHA, which banks use to load into their mainframes and transmit to ACH. A NACHA file is simple to make but exacting. I demonstrated this code at last year's Southwest Fox (plug, come to Southwest Fox everyone).

I have tried to edit out the stuff specific to this app, hopefully I did not edit out too much. The resulting text file is what gets sent to the bank. This code goes back to Foxpro Dos.
* we will have 1 master control record, a control record for each batch (typically 1), detail lines, then closing record for batch, closing record for
* master, then x number of padding lines at the end. You can have multiple batches, but many suggest to avoid that

*The first master control record:

* company means the company accepting the ACH pmts into their bank account

CREATE CURSOR curNacha (nacha c (94))

m.f1=space(94)
m.f1=stuff(m.f1, 1, 1,'1')  		 &&   1 record type code - 1 is master
m.f1=stuff(m.f1, 2, 2,'01')         &&   2 priority code - always use 01
m.f1=stuff(m.f1, 4,10,' '+lcBankNum) &&   3 company bank account number or id, i.e. 102345678 but alphanumeric
m.f1=stuff(m.f1,14,10,' '+lcBankNum) &&   4 same as 3
m.f1=stuff(m.f1,24, 6,lcYYMMDD)      &&   5 file creation date
m.f1=stuff(m.f1,30, 4,lcStrtTm)      &&   6 file creation time format 0230
m.f1=stuff(m.f1,34, 1,'A')           &&   7 file id modifier - use A
m.f1=stuff(m.f1,35, 3,'094')         &&   8 record size - must be 94 characters
m.f1=stuff(m.f1,38, 2,'10')          &&   9 blocking factor - use 10
m.f1=stuff(m.f1,40, 1,'1')           &&  10 format code - use 1
m.f1=stuff(m.f1,41,23,lcBankName)    &&  11 company bank name, i.e. First National
m.f1=stuff(m.f1,64,23,lcBankName)    &&  12 company bank name, same as #11
m.f1=stuff(m.f1,87, 8,' ')            &&  13 reference code - do not know purpose

* Then insert that as first record in the  cursor 


*Now make one record for the company, which will be the cursor's second record:

m.f1=space(94)
m.f1=stuff(m.f1, 1, 1,'5')                 &&   1 record type code - 5
m.f1=stuff(m.f1, 2, 3,'200')               &&   2 service class code - 200
m.f1=stuff(m.f1, 5,16,Dr_Name)             &&   3 company name, i.e. Jones Trade School
m.f1=stuff(m.f1,21,20,space(20))           &&   4 company disc data  - blank
m.f1=stuff(m.f1,41,10,Dr_Num)              &&   5 company EFT id/account given by bank (?)
m.f1=stuff(m.f1,51, 3,'PPD')               &&   6 std entry class code - always use PPD
m.f1=stuff(m.f1,54,10,'PENDINGEFT')        &&   7 company entry desc - 10 chars content whatever desc you want
m.f1=stuff(m.f1,64, 6,lcMMDDYY)            &&   8 company desc date - same as 9
m.f1=stuff(m.f1,70, 6,lcYYMMDD)            &&   9 eft entry date - same as 8
m.f1=stuff(m.f1,76, 3,'   ')               &&  10 settlement date julian - blank
m.f1=stuff(m.f1,79, 1,'0')                 &&  11 originator status code - 0
m.f1=stuff(m.f1,80, 8,left(lcBankNum,8))   &&  12 dfi id - comp.bank acct #, same as #3 in first record
m.f1=stuff(m.f1,88, 7,'0000001')           &&  13 batch # - usually 0000001

*Then insert that as the next (second) record in the cursor.


*Now loop and create a record for each ACH transaction and insert into cursor as records number 3 - X.  You will need a couple of additional vars:

*	count of records starting with 1,2,3 etc (knt) 
*       running total of charges (lnTOT1)
*	Total value of left 8 digits of bank routing number (totbanknum)



m.f1=space(94)
m.f1=stuff(m.f1, 1, 1,'6')     &&   1 record type code - always 6
m.f1=stuff(m.f1, 2, 2,'27')    &&   2 transaction code - always 27
m.f1=stuff(m.f1, 4, 9,jcBankNum)  &&   3/4 receiving dfi id + chk digit      - often called routing number - of payer's bank
m.f1=stuff(m.f1,13,17,achBankAcctNum)  &&   5 dfi acct # - account number of payers account at bank
m.f1=stuff(m.f1,30,10,amount)   && 6 payer amount to be deducted - 10 digit string left padded with 0's
m.f1=stuff(m.f1,40,15,personID)  	   && 7 payer's indiv id #, create as desired
m.f1=stuff(m.f1,55,22,padr(lcName,22))     &&   8 payer's name name      
m.f1=stuff(m.f1,77, 2,'  ')                &&   9 disc data - leave blank
m.f1=stuff(m.f1,79, 1,'0')                 &&  10 addenda record indicator
m.f1=stuff(m.f1,80,15,left(lcBankNum,8)+padl(alltrim(str(knt)),7,'0'))  &&  11 trace # - knt is number of entry within batch

* after looping thru details,
*two steps left: first create a closing batch record and insert it into the cursor:
 
jTotBankNum=right(str(TotBankNum,30),10)
  
m.f1=space(94)
m.f1=stuff(m.f1, 1, 1,'8')  && company control   && 1 record type code
m.f1=stuff(m.f1, 2, 3,'200')                    && 2 service class code
m.f1=stuff(m.f1, 5, 6, padl(alltr(str(knt)),6,'0')) &&   3 entry/addenda count
m.f1=stuff(m.f1,11,10,jTotBankNum)   &&   4 entry hash      
m.f1=stuff(m.f1,21,12,padl(alltrim(str(lnTOT1*100)) ,12, '0')) && total debit entry $ 
m.f1=stuff(m.f1,33,12,'000000000000')          &&   6 total credit entry $ amount
m.f1=stuff(m.f1,45,10,Dr_Num)                  &&   7 company id again
m.f1=stuff(m.f1,55,19,space(19))               &&   8 msg auth code
m.f1=stuff(m.f1,74, 6,space(6))                &&   9 reserved
m.f1=stuff(m.f1,80, 8,left(lcBanknum,8))       &&  10 company bank account number again
m.f1=stuff(m.f1,88, 7,'0000001')               &&  11 batch #

*Finally, create a closing master record and insert it into the cursor:
 
nBlock=int((knt+4+nAddl)/10)
nAddl=iif(mod(knt+4,10)#0,10-mod(knt+4,10),0)

m.f1=space(94)
m.f1=stuff(m.f1, 1, 1,'9')  &&file control      && 1 record type code
m.f1=stuff(m.f1, 2, 6,'000001')                 &&   2 batch count
m.f1=stuff(m.f1, 8, 6,padl(alltr(str(nBlock)),6,'0'))      &&3 block count
m.f1=stuff(m.f1,14, 8,padl(alltr(str(knt)),8,'0'))         &&   4 entry/addenda count
m.f1=stuff(m.f1,22,10,jTotBankNum)                        &&   5 entry hash
m.f1=stuff(m.f1,32,12,padl(alltr(str(lnTOT1*100)),12,'0'))   &&   6 total debit $
m.f1=stuff(m.f1,44,12,'000000000000')          &&   7 total credit entry $ 
m.f1=stuff(m.f1,56,39,' ')                 &&   8 reserved


*Whoops!  NACHA files must be read by mainframes and have an evenly divisible number of records. 

*Find how many more we need:


*And pad the cursor wth records of all 9's

for jnX=1 to nAddl
	insert into curNacha (nacha) values (repl('9',94))
endfor

COPY ALL TO (filename) TYPE SDF
>I need to create a file in ACH format.
>
>I did it eons ago in foxbase, but have lost that code.
>
>Does anyone have some code to share?
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform