diff --git a/README.md b/README.md index 4afbdf255..5a11c8ab5 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ ACH is under active development but already in production for multiple companies | RCK | Represented Check Entries | [Link](test/ach-rck-read/main.go) | [Link](test/ach-rck-write/main.go) | | SHR | Shared Network Entry | [Link](test/ach-shr-read/main.go) | [Link](test/ach-shr-write/main.go) | | TEL | Telephone-Initiated Entry | [Link](test/ach-tel-read/main.go) | [Link](test/ach-tel-write/main.go) | +| TRC | Truncated Check Entry | [Link](test/ach-trc-read/main.go) | [Link](test/ach-trc-write/main.go) | | WEB | Internet-initiated Entries | [Link](test/ach-web-read/main.go) | [Link](test/ach-web-write/main.go) | | XCK | Destroyed Check Entry | [Link](test/ach-xck-read/main.go) | [Link](test/ach-xck-write/main.go) | diff --git a/advEntryDetail.go b/advEntryDetail.go index b4fd1689b..159ab17a6 100644 --- a/advEntryDetail.go +++ b/advEntryDetail.go @@ -88,6 +88,7 @@ func NewADVEntryDetail() *ADVEntryDetail { // Parse provides no guarantee about all fields being filled in. Callers should make a Validate() call to confirm // successful parsing and data validity. +// Parse ADVEntryDetail func (ed *ADVEntryDetail) Parse(record string) { if utf8.RuneCountInString(record) != 94 { return diff --git a/batch.go b/batch.go index 1bdb47bbb..559d9f6db 100644 --- a/batch.go +++ b/batch.go @@ -79,12 +79,12 @@ func NewBatch(bh *BatchHeader) (Batcher, error) { return nil, &FileError{FieldName: "StandardEntryClassCode", Value: bh.StandardEntryClassCode, Msg: msg} } -// Create creates a batch +// Create returns error for using an implementation of batch or NewBatch" func (batch *Batch) Create() error { return errors.New("use an implementation of batch or NewBatch") } -// Validate validates a batch +// Validate returns an error for using an use an implementation of batch or NewBatch func (batch *Batch) Validate() error { return errors.New("use an implementation of batch or NewBatch") } @@ -309,17 +309,17 @@ func (batch *Batch) AddEntry(entry *EntryDetail) { batch.Entries = append(batch.Entries, entry) } -// GetADVEntries returns a slice of ADV entry details for the batch -func (batch *Batch) GetADVEntries() []*ADVEntryDetail { - return batch.ADVEntries -} - -// AddADVEntry appends an EntryDetailADV to the Batch +// AddADVEntry appends an ADV EntryDetail to the Batch func (batch *Batch) AddADVEntry(entry *ADVEntryDetail) { batch.category = entry.Category batch.ADVEntries = append(batch.ADVEntries, entry) } +// GetADVEntries returns a slice of entry details for the batch +func (batch *Batch) GetADVEntries() []*ADVEntryDetail { + return batch.ADVEntries +} + // Category returns batch category func (batch *Batch) Category() string { return batch.category diff --git a/batchENR.go b/batchENR.go index fb4b2200a..57aa4a317 100644 --- a/batchENR.go +++ b/batchENR.go @@ -18,6 +18,7 @@ type BatchENR struct { Batch } +// NewBatchENR returns a *BatchENR func NewBatchENR(bh *BatchHeader) *BatchENR { batch := new(BatchENR) batch.SetControl(NewBatchControl()) @@ -77,6 +78,7 @@ func (batch *BatchENR) Create() error { return batch.Validate() } +// ENRPaymentInformation structure type ENRPaymentInformation struct { // TransactionCode is the Transaction Code of the holder's account // Values: 22 (Demand Credit), 27 (Demand Debit), 32 (Savings Credit), 37 (Savings Debit) diff --git a/batchHeader.go b/batchHeader.go index 1c512e20e..7ff08d5a7 100644 --- a/batchHeader.go +++ b/batchHeader.go @@ -300,9 +300,8 @@ func (bh *BatchHeader) EffectiveEntryDateField() string { // ENR records require EffectiveEntryDate to be space filled. NACHA Page OR108 if bh.CompanyEntryDescription == "AUTOENROLL" { return bh.alphaField("", 6) // YYMMDD - } else { - return bh.formatSimpleDate(bh.EffectiveEntryDate) } + return bh.formatSimpleDate(bh.EffectiveEntryDate) } // ODFIIdentificationField get the odfi number zero padded diff --git a/batchMTE.go b/batchMTE.go index 8630b1ee0..ed02a95e0 100644 --- a/batchMTE.go +++ b/batchMTE.go @@ -18,6 +18,7 @@ type BatchMTE struct { Batch } +// NewBatchMTE returns a *BatchMTE func NewBatchMTE(bh *BatchHeader) *BatchMTE { batch := new(BatchMTE) batch.SetControl(NewBatchControl()) diff --git a/batchTRC.go b/batchTRC.go index 29bf9ae24..bfd32f8dc 100644 --- a/batchTRC.go +++ b/batchTRC.go @@ -8,7 +8,7 @@ import "fmt" // BatchTRC holds the BatchHeader and BatchControl and all EntryDetail for TRC Entries. // -//Truncated Entry is used to identify a debit entry of a truncated check. +// Truncated Entry is used to identify a debit entry of a truncated check. type BatchTRC struct { Batch } diff --git a/batchTRC_test.go b/batchTRC_test.go index 7fdd78b3d..85a853d3b 100644 --- a/batchTRC_test.go +++ b/batchTRC_test.go @@ -471,3 +471,14 @@ func TestBatchTRCItemResearchNumber(t *testing.T) { } } } + +// TestBatchTRCItemTypeIndicator returns an error if ItemTypeIndicator is 01. +func TestBatchTRCItemTypeIndicator(t *testing.T) { + mockBatch := NewBatchTRC(mockBatchTRCHeader()) + mockBatch.AddEntry(mockTRCEntryDetail()) + mockBatch.Create() + + if mockBatch.GetEntries()[0].ItemTypeIndicator() != "01" { + t.Error("ItemTypeIndicator does not validate") + } +} diff --git a/file.go b/file.go index 33d856c75..eff37a53f 100644 --- a/file.go +++ b/file.go @@ -93,17 +93,17 @@ type fileControl struct { Control FileControl `json:"fileControl"` } -type fileADVControl struct { - ControlADV ADVFileControl `json:"fileADVControl"` +type advFileControl struct { + ADVControl ADVFileControl `json:"advFileControl"` } -// FileFromJson attempts to return a *File object assuming the input is valid JSON. +// FileFromJSON attempts to return a *File object assuming the input is valid JSON. // // Callers should always check for a nil-error before using the returned file. // // The File returned may not be valid and callers should confirm with Validate(). Invalid files may // be rejected by other Financial Institutions or ACH tools. -func FileFromJson(bs []byte) (*File, error) { +func FileFromJSON(bs []byte) (*File, error) { if len(bs) == 0 { return nil, errors.New("no JSON data provided") } @@ -135,17 +135,17 @@ func FileFromJson(bs []byte) (*File, error) { file.Control = control.Control } else { // Read ADVFileControl - controlADV := fileADVControl{ - ControlADV: NewADVFileControl(), + advControl := advFileControl{ + ADVControl: NewADVFileControl(), } - if err := json.NewDecoder(bytes.NewReader(bs)).Decode(&controlADV); err != nil { - return nil, fmt.Errorf("problem reading FileADVControl: %v", err) + if err := json.NewDecoder(bytes.NewReader(bs)).Decode(&advControl); err != nil { + return nil, fmt.Errorf("problem reading ADVFileControl: %v", err) } - file.ADVControl = controlADV.ControlADV + file.ADVControl = advControl.ADVControl } // Build resulting file - if err := file.setBatchesFromJson(bs); err != nil { + if err := file.setBatchesFromJSON(bs); err != nil { return nil, err } file.Header = header.Header @@ -159,7 +159,7 @@ func FileFromJson(bs []byte) (*File, error) { return file, nil } -// UnmarshalJSON returns an error when json struct tag unmarshal is used +// UnmarshalJSON returns error json struct tag unmarshal is deprecated, use ach.FileFromJSON instead func (f *File) UnmarshalJSON(p []byte) error { return errors.New("json struct tag unmarshal is deprecated, use ach.FileFromJSON instead") } @@ -172,7 +172,7 @@ type batchesJSON struct { // // We have to break this out as Batcher is an interface (and can't be read by Go's // json struct tag decoding). -func (f *File) setBatchesFromJson(bs []byte) error { +func (f *File) setBatchesFromJSON(bs []byte) error { var batches batchesJSON if err := json.Unmarshal(bs, &batches); err != nil { return err diff --git a/file_test.go b/file_test.go index 4c1c76282..a79889b45 100644 --- a/file_test.go +++ b/file_test.go @@ -396,7 +396,7 @@ func TestFile__readFromJson(t *testing.T) { t.Fatal(err) } - file, err := FileFromJson(bs) + file, err := FileFromJSON(bs) if err != nil { t.Fatal(err) } diff --git a/reader.go b/reader.go index 2b0277085..1673a8644 100644 --- a/reader.go +++ b/reader.go @@ -76,12 +76,12 @@ func (e ErrorList) Print(w io.Writer) { } } -// Empty is an Empty ErrorList +// Empty no errors to return func (e ErrorList) Empty() bool { return e == nil || len(e) == 0 } -// MarshalJSON marshals errors +// MarshalJSON marshals error list func (e ErrorList) MarshalJSON() ([]byte, error) { return json.Marshal(e.Error()) } @@ -200,7 +200,6 @@ func (r *Reader) Read() (File, error) { return r.File, nil } return r.File, r.errors - } func (r *Reader) processFixedWidthFile(line *string) error { diff --git a/server/files.go b/server/files.go index 9dc159a73..1448ab335 100644 --- a/server/files.go +++ b/server/files.go @@ -80,7 +80,7 @@ func decodeCreateFileRequest(_ context.Context, request *http.Request) (interfac h := request.Header.Get("Content-Type") if strings.Contains(h, "application/json") { // Read body as ACH file in JSON - f, err := ach.FileFromJson(bs) + f, err := ach.FileFromJSON(bs) if err != nil { return nil, err } diff --git a/version.go b/version.go index 7b949cb4f..bf881b9c0 100644 --- a/version.go +++ b/version.go @@ -4,5 +4,5 @@ package ach -// Version of ACH library +// Version Number const Version = "v0.4.1-dev"