Skip to content

Commit

Permalink
Support acknowledgment entries - ACK & ATX #327
Browse files Browse the repository at this point in the history
Initial ACK Support
  • Loading branch information
bkmoovio committed Oct 26, 2018
1 parent 8e9c346 commit ac7847b
Show file tree
Hide file tree
Showing 6 changed files with 423 additions and 2 deletions.
6 changes: 6 additions & 0 deletions batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,16 @@ type batch struct {
// NewBatch takes a BatchHeader and returns a matching SEC code batch type that is a batcher. Returns an error if the SEC code is not supported.
func NewBatch(bh *BatchHeader) (Batcher, error) {
switch bh.StandardEntryClassCode {
case "ACK":
return NewBatchACK(bh), nil
case "ARC":
return NewBatchARC(bh), nil
case "BOC":
return NewBatchBOC(bh), nil
/* case "CCD", "ATX":
return NewBatchCCD(bh), nil
ToDo: Should we do it this way and slash up batchCCD?
*/
case "CCD":
return NewBatchCCD(bh), nil
case "CIE":
Expand Down
89 changes: 89 additions & 0 deletions batchACK.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2018 The Moov Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package ach

import (
"fmt"
)

// BatchACK is a batch file that handles SEC payment type ACK and ACK+.
// Acknowledgement of a Corporate credit by the Receiving Depository Financial Institution (RDFI).
// For commercial accounts only.
type BatchACK struct {
batch
}

var (
msgBatchTransactionCodeACK = "%v transaction code not equal to 24 or 34 for SEC code %v"
msgBatchAmountACK = "%v amount must be zero for SEC code %v"
)

// NewBatchACK returns a *BatchACK
func NewBatchACK(bh *BatchHeader) *BatchACK {
batch := new(BatchACK)
batch.SetControl(NewBatchControl())
batch.SetHeader(bh)
return batch
}

// Validate ensures the batch meets NACHA rules specific to this batch type.
func (batch *BatchACK) Validate() error {
// basic verification of the batch before we validate specific rules.
if err := batch.verify(); err != nil {
return err
}
// Add configuration and type specific validation.
if batch.Header.StandardEntryClassCode != "ACK" {
msg := fmt.Sprintf(msgBatchSECType, batch.Header.StandardEntryClassCode, "ACK")
return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: "StandardEntryClassCode", Msg: msg}
}
// Range through Entries
for _, entry := range batch.Entries {
// Amount must be zero for Acknowledgement Entries
if entry.Amount > 0 {
msg := fmt.Sprintf(msgBatchAmountACK, entry.Amount, "ACK")
return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: "Amount", Msg: msg}
}
// TransactionCode must be either 24 or 34 for Acknowledgement Entries
switch entry.TransactionCode {
case 24, 34:
default:
msg := fmt.Sprintf(msgBatchTransactionCodeACK, entry.TransactionCode, "ACK")
return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: "Transaction Code", Msg: msg}
}

// ACK can have up to one Record TypeCode = 05, or there can be a NOC (98) or Return (99)
for _, addenda := range entry.Addendum {
switch entry.Category {
case CategoryForward:
if err := batch.categoryForwardAddenda05(entry, addenda); err != nil {
return err
}
if len(entry.Addendum) > 1 {
msg := fmt.Sprintf(msgBatchAddendaCount, len(entry.Addendum), 1, batch.Header.StandardEntryClassCode)
return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: "AddendaCount", Msg: msg}
}
case CategoryNOC:
if err := batch.categoryNOCAddenda98(entry, addenda); err != nil {
return err
}
case CategoryReturn:
if err := batch.categoryReturnAddenda99(entry, addenda); err != nil {
return err
}
}
}
}
return nil
}

// Create builds the batch sequence numbers and batch control. Additional creation
func (batch *BatchACK) Create() error {
// generates sequence numbers and batch control
if err := batch.build(); err != nil {
return err
}
return batch.Validate()
}
Loading

0 comments on commit ac7847b

Please sign in to comment.