Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support acknowledgment entries ack & atx #327 #331

Merged
merged 10 commits into from
Oct 30, 2018
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ Docs: [docs.moov.io](https://docs.moov.io/en/latest/) | [api docs](https://api.m
ACH is under active development but already in production for multiple companies. Please star the project if you are interested in its progress.

* Library currently supports the reading and writing
* ACK (Acknowledgment Entry for CCD)
* ARC (Accounts Receivable Entry)
* ATX (Acknowledgment Entry for CTX)
* BOC (Back Office Conversion)
* CCD (Corporate credit or debit)
* CIE (Customer-Initiated Entry)
Expand Down
4 changes: 4 additions & 0 deletions batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ 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 "ATX":
return NewBatchATX(bh), nil
case "BOC":
return NewBatchBOC(bh), nil
case "CCD":
Expand Down
84 changes: 84 additions & 0 deletions batchACK.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// 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
}

// 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(msgBatchAmountZero, 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(msgBatchTransactionCode, entry.TransactionCode, "ACK")
return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: "TransactionCode", 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