View in color | License | Download script | History | Other scripts by: swhite |
30-Apr 14:11 UTC
[0.083] 24.091k
[0.083] 24.091k
rpps.rREBOL [
Title: "Read a Remote Payment and Presentation System file"
Author: "Steven White"
File: %rpps.r
Date: 7-Nov-2011
Purpose: {This is a module for reading and taking apart a modified
NACHA file used in the Remote Payment and Presentation System.
If those terms mean anything, this could be a useful module.
If those terms mean nothing, then at least this module could be an
example of a way to handle a text file of fixed-format records.
In 25 words or less, a NACHA file is a file of fixed-format text
records containing information about bank transfers. The records
are of several different types (headers, detail, trailers)
differentiated by a code in the first character of each record.}
library: [
level: 'beginner
platform: 'all
type: [tutorial tool]
domain: [text-processing file-handling]
tested-under: none
support: none
license: none
see-also: none
]
]
;; [---------------------------------------------------------------------------]
;; [ This module defines a text file in the RPPS format for ]
;; [ getting money electronically from the bank. ]
;; [ RPPS stands for Remote Payment and Presentment System. ]
;; [ This is a "modified NACHA" format and is not quite the same ]
;; [ as the file that WE send TO the bank for automatic payments. ]
;; [---------------------------------------------------------------------------]
;; [---------------------------------------------------------------------------]
;; [ This function accepts a string, a starting position, and an ]
;; [ ending position, and returns a substring from the starting ]
;; [ position to the ending position. If the ending position is -1, ]
;; [ the procedure returns the substring from the starting position ]
;; [ to the end of the string. ]
;; [ This technique was "borrowed" from the REBOL library. ]
;; [---------------------------------------------------------------------------]
GLB-SUBSTRING: func [
"Return a substring from the start position to the end position"
INPUT-STRING [series!] "Full input string"
START-POS [number!] "Starting position of substring"
END-POS [number!] "Ending position of substring"
] [
if END-POS = -1 [END-POS: length? INPUT-STRING]
return skip (copy/part INPUT-STRING END-POS) (START-POS - 1)
]
;; [---------------------------------------------------------------------------]
;; [ Various data items used in processing the file. ]
;; [---------------------------------------------------------------------------]
RPPS-FILE: [] ;; Holds the whole file in memory
RPPS-FILE-ID: %ACH.txt ;; Default name of the file
RPPS-EOF: false ;; End-of-file flag for reading
RPPS-REC: "" ;; One record, for reading or writing
RPPS-REC-COUNT: 0 ;; Counter, upped by 1 as we read or write
RPPS-CURRENT-TYPE: "" ;; Type code of record in memory
;; [---------------------------------------------------------------------------]
;; [ When we read a record, we will take it apart in to its ]
;; [ fields and store the fields below. The CURRENT-TYPE field ]
;; [ indicates which record we currently have our hands on. ]
;; [ For those record that contain numbers or amounts, some of the ]
;; [ numbers or amounts are converted to appropriate data types ]
;; [ so they can be used in appropriate ways (currency, for example). ]
;; [---------------------------------------------------------------------------]
RPPS-1-RECORD-TYPE-CODE: ""
RPPS-1-PRIORITY-CODE: ""
RPPS-1-IMMEDIATE-DESTINATION: ""
RPPS-1-IMMEDIATE-ORIGIN: ""
RPPS-1-TRANSMISSION-DATE: ""
RPPS-1-TRANSMISSION-TIME: ""
RPPS-1-FILE-ID-MODIFIER: ""
RPPS-1-RECORD-SIZE: ""
RPPS-1-BLOCKING-FACTOR: ""
RPPS-1-FORMAT-CODE: ""
RPPS-1-DESTINATION-NAME: ""
RPPS-1-ORIGIN: ""
RPPS-1-REFERENCE-CODE: ""
RPPS-5-RECORD-TYPE-CODE: ""
RPPS-5-SERVICE-CLASS-CODE: ""
RPPS-5-BILLER-NAME: ""
RPPS-5-RESERVED: ""
RPPS-5-BILLER-ID-NUMBER: ""
RPPS-5-ENTRY-CLASS: ""
RPPS-5-ENTRY-DESCRIPTION: ""
RPPS-5-DESCRIPTIVE-DATE: ""
RPPS-5-EFFECTIVE-DATE: ""
RPPS-5-SETTLEMENT-DATE: ""
RPPS-5-CONCENTRATOR-STATUS: ""
RPPS-5-RPPS-ID-NUMBER: ""
RPPS-5-BATCH-NUMBER: ""
RPPS-5-EFFECTIVE-DATE-E: ""
RPPS-6-RECORD-TYPE-CODE: ""
RPPS-6-TRANSACTION-CODE: ""
RPPS-6-RPPS-ID-NUMBER: ""
RPPS-6-MERCHANT-ACCOUNT-NBR: ""
RPPS-6-AMOUNT: ""
RPPS-6-CONSUMER-ACCOUNT-NBR: ""
RPPS-6-CONSUMER-NAME: ""
RPPS-6-RPPS-FLAG: ""
RPPS-6-ADDENDUM-RECORD-IND: ""
RPPS-6-TRACE-NUMBER: ""
RPPS-6-SEQUENCE-NUMBER: ""
RPPS-6-AMOUNT-N: ""
RPPS-8-RECORD-TYPE-CODE: ""
RPPS-8-SERVICE-CLASS-CODE: ""
RPPS-8-ENTRY-ADDENDA-COUNT: ""
RPPS-8-ENTRY-HASH: ""
RPPS-8-TOTAL-DEBIT: ""
RPPS-8-TOTAL-CREDIT: ""
RPPS-8-BILLER-ID-NUMBER: ""
RPPS-8-MAC: ""
RPPS-8-FILLER-1: ""
RPPS-8-RPPS-ID-NUMBER: ""
RPPS-8-BATCH-NUMBER: ""
RPPS-8-TOTAL-DEBIT-N: ""
RPPS-8-TOTAL-CREDIT-N: ""
RPPS-9-RECORD-TYPE-CODE: ""
RPPS-9-BATCH-COUNT: ""
RPPS-9-BLOCK-COUNT: ""
RPPS-9-ENTRY-ADDENDA-COUNT: ""
RPPS-9-ENTRY-HASH: ""
RPPS-9-TOTAL-DEBIT: ""
RPPS-9-TOTAL-CREDIT: ""
RPPS-9-FILLER-1: ""
;; [---------------------------------------------------------------------------]
;; [ This procedure reads the whole file into memory and takes off any ]
;; [ records at the end that might be all "9" (which would be padding ]
;; [ records). ]
;; [---------------------------------------------------------------------------]
RPPS-OPEN-INPUT: does [
RPPS-FILE: copy []
RPPS-FILE: read/lines RPPS-FILE-ID
RPPS-EOF: false
RPPS-REC-COUNT: 0
remove-each TEST-STRING RPPS-FILE [= GLB-SUBSTRING TEST-STRING 1 10 "9999999999"]
]
;; [---------------------------------------------------------------------------]
;; [ This procedure "reads" the "file," which, in this situation, means that ]
;; [ it locates the next line in the in-memory copy of the file, and takes ]
;; [ that fixed-format line apart into its various data items. ]
;; [ If there are no more lines to "read," it sets an end-of-file flag. ]
;; [---------------------------------------------------------------------------]
RPPS-READ: does [
RPPS-REC-COUNT: RPPS-REC-COUNT + 1
RPPS-REC: copy ""
RPPS-CURRENT-TYPE: copy ""
RPPS-REC: pick RPPS-FILE RPPS-REC-COUNT
if none? RPPS-REC [
RPPS-EOF: true
]
if not RPPS-EOF [
RPPS-UNSTRING-RECORD
]
]
;; [---------------------------------------------------------------------------]
;; [ This procedure "closes" the file, which means it clears out the ]
;; [ memory area that held the data. ]
;; [---------------------------------------------------------------------------]
RPPS-CLOSE-INPUT: does [
RPPS-FILE: copy []
RPPS-REC: copy ""
]
;; [---------------------------------------------------------------------------]
;; [ This module is incomplete. It does not include any procedure for ]
;; [ creating a NACHA file. The Remote Payment and Presentation System ]
;; [ seems to be for getting money from the bank anyway, and not going ]
;; [ after it ourselves. ]
;; [ If one wanted to create a file, one could reverse the reading process ]
;; [ by converting the data items to strings of appropriate lengths, and ]
;; [ joining them all together, with a newline at the end of each. ]
;; [---------------------------------------------------------------------------]
RPPS-OPEN-OUTPUT: does [
RPPS-FILE: copy []
RPPS-REC: copy ""
RPPS-REC-COUNT: 0
]
RPPS-WRITE: does [
append RPPS-FILE RPPS-REC
RPPS-REC-COUNT: RPPS-REC-COUNT + 1
]
RPPS-CLOSE-OUTPUT: does [
write/lines RPPS-FILE-ID RPPS-FILE
RPPS-FILE: copy []
RPPS-REC: copy ""
]
;; [---------------------------------------------------------------------------]
;; [ This procedure is performed after reading each record. ]
;; [ It takes apart the fixed-format record into individual data items ]
;; [ that can be used in whatever ways the caller wants. ]
;; [ Records are differentiated by a type code in the first character. ]
;; [---------------------------------------------------------------------------]
RPPS-UNSTRING-RECORD: does [
RPPS-CURRENT-TYPE: GLB-SUBSTRING RPPS-REC 1 1
if RPPS-CURRENT-TYPE = "1" [
RPPS-UNSTRING-1
]
if RPPS-CURRENT-TYPE = "5" [
RPPS-UNSTRING-5
]
if RPPS-CURRENT-TYPE = "6" [
RPPS-UNSTRING-6
]
if RPPS-CURRENT-TYPE = "8" [
RPPS-UNSTRING-8
]
if RPPS-CURRENT-TYPE = "9" [
RPPS-UNSTRING-9
]
]
RPPS-UNSTRING-1: does [
RPPS-1-RECORD-TYPE-CODE: copy ""
RPPS-1-PRIORITY-CODE: copy ""
RPPS-1-IMMEDIATE-DESTINATION: copy ""
RPPS-1-IMMEDIATE-ORIGIN: copy ""
RPPS-1-TRANSMISSION-DATE: copy ""
RPPS-1-TRANSMISSION-TIME: copy ""
RPPS-1-FILE-ID-MODIFIER: copy ""
RPPS-1-RECORD-SIZE: copy ""
RPPS-1-BLOCKING-FACTOR: copy ""
RPPS-1-FORMAT-CODE: copy ""
RPPS-1-DESTINATION-NAME: copy ""
RPPS-1-ORIGIN: copy ""
RPPS-1-REFERENCE-CODE: copy ""
RPPS-1-RECORD-TYPE-CODE: GLB-SUBSTRING RPPS-REC 1 1
RPPS-1-PRIORITY-CODE: GLB-SUBSTRING RPPS-REC 2 3
RPPS-1-IMMEDIATE-DESTINATION: GLB-SUBSTRING RPPS-REC 4 13
RPPS-1-IMMEDIATE-ORIGIN: GLB-SUBSTRING RPPS-REC 14 23
RPPS-1-TRANSMISSION-DATE: GLB-SUBSTRING RPPS-REC 24 29
RPPS-1-TRANSMISSION-TIME: GLB-SUBSTRING RPPS-REC 30 33
RPPS-1-FILE-ID-MODIFIER: GLB-SUBSTRING RPPS-REC 34 34
RPPS-1-RECORD-SIZE: GLB-SUBSTRING RPPS-REC 35 37
RPPS-1-BLOCKING-FACTOR: GLB-SUBSTRING RPPS-REC 38 39
RPPS-1-FORMAT-CODE: GLB-SUBSTRING RPPS-REC 40 40
RPPS-1-DESTINATION-NAME: GLB-SUBSTRING RPPS-REC 41 63
RPPS-1-ORIGIN: GLB-SUBSTRING RPPS-REC 64 86
RPPS-1-REFERENCE-CODE: GLB-SUBSTRING RPPS-REC 87 94
]
RPPS-UNSTRING-5: does [
RPPS-5-RECORD-TYPE-CODE: copy ""
RPPS-5-SERVICE-CLASS-CODE: copy ""
RPPS-5-BILLER-NAME: copy ""
RPPS-5-RESERVED: copy ""
RPPS-5-BILLER-ID-NUMBER: copy ""
RPPS-5-ENTRY-CLASS: copy ""
RPPS-5-ENTRY-DESCRIPTION: copy ""
RPPS-5-DESCRIPTIVE-DATE: copy ""
RPPS-5-EFFECTIVE-DATE: copy ""
RPPS-5-SETTLEMENT-DATE: copy ""
RPPS-5-CONCENTRATOR-STATUS: copy ""
RPPS-5-RPPS-ID-NUMBER: copy ""
RPPS-5-BATCH-NUMBER: copy ""
RPPS-5-RECORD-TYPE-CODE: GLB-SUBSTRING RPPS-REC 1 1
RPPS-5-SERVICE-CLASS-CODE: GLB-SUBSTRING RPPS-REC 2 4
RPPS-5-BILLER-NAME: GLB-SUBSTRING RPPS-REC 5 20
RPPS-5-RESERVED: GLB-SUBSTRING RPPS-REC 21 40
RPPS-5-BILLER-ID-NUMBER: GLB-SUBSTRING RPPS-REC 41 50
RPPS-5-ENTRY-CLASS: GLB-SUBSTRING RPPS-REC 51 53
RPPS-5-ENTRY-DESCRIPTION: GLB-SUBSTRING RPPS-REC 54 63
RPPS-5-DESCRIPTIVE-DATE: GLB-SUBSTRING RPPS-REC 64 69
RPPS-5-EFFECTIVE-DATE: GLB-SUBSTRING RPPS-REC 70 75
RPPS-5-SETTLEMENT-DATE: GLB-SUBSTRING RPPS-REC 76 78
RPPS-5-CONCENTRATOR-STATUS: GLB-SUBSTRING RPPS-REC 79 79
RPPS-5-ID-NUMBER: GLB-SUBSTRING RPPS-REC 80 87
RPPS-5-BATCH-NUMBER: GLB-SUBSTRING RPPS-REC 88 94
RPPS-5-EFFECTIVE-DATE-E: rejoin [
GLB-SUBSTRING RPPS-5-EFFECTIVE-DATE 3 4
"/"
GLB-SUBSTRING RPPS-5-EFFECTIVE-DATE 5 6
"/"
"20"
GLB-SUBSTRING RPPS-5-EFFECTIVE-DATE 1 2
]
]
RPPS-UNSTRING-6: does [
RPPS-6-RECORD-TYPE-CODE: copy ""
RPPS-6-TRANSACTION-CODE: copy ""
RPPS-6-RPPS-ID-NUMBER: copy ""
RPPS-6-MERCHANT-ACCOUNT-NBR: copy ""
RPPS-6-AMOUNT: copy ""
RPPS-6-CONSUMER-ACCOUNT-NBR: copy ""
RPPS-6-CONSUMER-NAME: copy ""
RPPS-6-RPPS-FLAG: copy ""
RPPS-6-ADDENDUM-RECORD-IND: copy ""
RPPS-6-TRACE-NUMBER: copy ""
RPPS-6-SEQUENCE-NUMBER: copy ""
RPPS-6-RECORD-TYPE-CODE: GLB-SUBSTRING RPPS-REC 1 1
RPPS-6-TRANSACTION-CODE: GLB-SUBSTRING RPPS-REC 2 3
RPPS-6-RPPS-ID-NUMBER: GLB-SUBSTRING RPPS-REC 4 12
RPPS-6-MERCHANT-ACCOUNT-NBR: GLB-SUBSTRING RPPS-REC 13 29
RPPS-6-AMOUNT: GLB-SUBSTRING RPPS-REC 30 39
RPPS-6-CONSUMER-ACCOUNT-NBR: GLB-SUBSTRING RPPS-REC 40 54
RPPS-6-CONSUMER-NAME: GLB-SUBSTRING RPPS-REC 55 76
RPPS-6-RPPS-FLAG: GLB-SUBSTRING RPPS-REC 77 78
RPPS-6-ADDENDUM-RECORD-IND: GLB-SUBSTRING RPPS-REC 79 79
RPPS-6-TRACE-NUMBER: GLB-SUBSTRING RPPS-REC 80 87
RPPS-6-SEQUENCE-NUMBER: GLB-SUBSTRING RPPS-REC 88 94
RPPS-6-AMOUNT-N: to-decimal divide to-decimal RPPS-6-AMOUNT 100
]
RPPS-UNSTRING-8: does [
RPPS-8-RECORD-TYPE-CODE: copy ""
RPPS-8-SERVICE-CLASS-CODE: copy ""
RPPS-8-ENTRY-ADDENDA-COUNT: copy ""
RPPS-8-ENTRY-HASH: copy ""
RPPS-8-TOTAL-DEBIT: copy ""
RPPS-8-TOTAL-CREDIT: copy ""
RPPS-8-BILLER-ID-NUMBER: copy ""
RPPT-8-MAC: copy ""
RPPS-8-FILLER-1: copy ""
RPPS-8-RPPS-ID-NUMBER: copy ""
RPPS-8-BATCH-NUMBER: copy ""
RPPS-8-RECORD-TYPE-CODE: GLB-SUBSTRING RPPS-REC 1 1
RPPS-8-SERVICE-CLASS-CODE: GLB-SUBSTRING RPPS-REC 2 4
RPPS-8-ENTRY-ADDENDA-COUNT: GLB-SUBSTRING RPPS-REC 5 10
RPPS-8-ENTRY-HASH: GLB-SUBSTRING RPPS-REC 11 20
RPPS-8-TOTAL-DEBIT: GLB-SUBSTRING RPPS-REC 21 32
RPPS-8-TOTAL-CREDIT: GLB-SUBSTRING RPPS-REC 33 44
RPPS-8-BILLER-ID-NUMBER: GLB-SUBSTRING RPPS-REC 45 54
RPPS-8-MAC: GLB-SUBSTRING RPPS-REC 55 73
RPPS-8-FILLER-1: GLB-SUBSTRING RPPS-REC 74 79
RPPS-8-RPPS-ID-NUMBER: GLB-SUBSTRING RPPS-REC 80 87
RPPS-8-BATCH-NUMBER: GLB-SUBSTRING RPPS-REC 88 94
RPPS-8-TOTAL-DEBIT-N: divide to-decimal RPPS-8-TOTAL-DEBIT 100
RPPS-8-TOTAL-CREDIT-N: divide to-decimal RPPS-8-TOTAL-CREDIT 100
]
RPPS-UNSTRING-9: does [
RPPS-9-RECORD-TYPE-CODE: copy ""
RPPS-9-BATCH-COUNT: copy ""
RPPS-9-BLOCK-COUNT: copy ""
RPPS-9-ENTRY-ADDENDA-COUNT: copy ""
RPPS-9-ENTRY-HASH: copy ""
RPPS-9-TOTAL-DEBIT: copy ""
RPPS-9-TOTAL-CREDIT: copy ""
RPPS-9-FILLER-1: copy ""
RPPS-9-RECORD-TYPE-CODE: GLB-SUBSTRING RPPS-REC 1 1
RPPS-9-BATCH-COUNT: GLB-SUBSTRING RPPS-REC 2 7
RPPS-9-BLOCK-COUNT: GLB-SUBSTRING RPPS-REC 8 13
RPPS-9-ENTRY-ADDENDA-COUNT: GLB-SUBSTRING RPPS-REC 14 21
RPPS-9-ENTRY-HASH: GLB-SUBSTRING RPPS-REC 22 31
RPPS-9-TOTAL-DEBIT: GLB-SUBSTRING RPPS-REC 32 43
RPPS-9-TOTAL-CREDIT: GLB-SUBSTRING RPPS-REC 44 55
RPPS-9-FILLER-1: GLB-SUBSTRING RPPS-REC 56 94
]
;; ----------------------------------------------------------------------------- |