Repository: moov-io/ach
Pull request #219 (2018-06-19 20:55:40)

#209 Add support for CIE 
#209 Add support for CIE 


Patch:
diff --git a/README.md b/README.md
index 26025e9d..b509942e 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ ACH is under active development but already in production for multiple companies
 	* ARC (Accounts Receivable Entry)
 	* BOC (Back Office Conversion)
 	* CCD (Corporate credit or debit)
+	* CIE (Customer-Initiated Entry)
 	* COR (Automated Notification of Change(NOC))
 	* POP (Point of Purchase)
 	* POS (Point of Sale)
diff --git a/batch.go b/batch.go
index 439305ae..c961c76e 100644
--- a/batch.go
+++ b/batch.go
@@ -33,6 +33,8 @@ func NewBatch(bh *BatchHeader) (Batcher, error) {
 		return NewBatchBOC(bh), nil
 	case "CCD":
 		return NewBatchCCD(bh), nil
+	case "CIE":
+		return NewBatchCIE(bh), nil
 	case "COR":
 		return NewBatchCOR(bh), nil
 	case "POP":
diff --git a/batchCIE.go b/batchCIE.go
new file mode 100644
index 00000000..2bdbaf8a
--- /dev/null
+++ b/batchCIE.go
@@ -0,0 +1,100 @@
+// Copyright 2018 The ACH 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"
+)
+
+// BatchCIE holds the BatchHeader and BatchControl and all EntryDetail for CIE Entries.
+//
+// Customer-Initiated Entry (or CIE entry) is a credit entry initiated on behalf of,
+// and upon the instruction of, a consumer to transfer funds to a non-consumer Receiver.
+// CIE entries are usually transmitted to a company for payment of funds that the consumer
+// owes to that company and are initiated by the consumer through some type of online
+// banking product or bill payment service provider. With CIEs, funds owed by the consumer
+// are “pushed” to the biller in the form of an ACH credit, as opposed to the biller’s use of
+// a debit application (e.g., PPD, WEB) to “pull” the funds from a customer’s account.
+type BatchCIE struct {
+	batch
+}
+
+var msgBatchCIEAddenda = "found and 1 Addenda05 is the maximum for SEC code CIE"
+var msgBatchCIEAddendaType = "%T found where Addenda05 is required for SEC code CIE"
+
+// NewBatchCIE returns a *BatchCIE
+func NewBatchCIE(bh *BatchHeader) *BatchCIE {
+	batch := new(BatchCIE)
+	batch.SetControl(NewBatchControl())
+	batch.SetHeader(bh)
+	return batch
+}
+
+// Validate checks valid NACHA batch rules. Assumes properly parsed records.
+func (batch *BatchCIE) Validate() error {
+	// basic verification of the batch before we validate specific rules.
+	if err := batch.verify(); err != nil {
+		return err
+	}
+	// Add configuration based validation for this type.
+
+	// Add type specific validation.
+
+	if batch.Header.StandardEntryClassCode != "CIE" {
+		msg := fmt.Sprintf(msgBatchSECType, batch.Header.StandardEntryClassCode, "CIE")
+		return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: "StandardEntryClassCode", Msg: msg}
+	}
+
+	// CIE detail entries can only be a debit, ServiceClassCode must allow debits
+	switch batch.Header.ServiceClassCode {
+	case 200, 225, 280:
+		msg := fmt.Sprintf(msgBatchServiceClassCode, batch.Header.ServiceClassCode, "CIE")
+		return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: "ServiceClassCode", Msg: msg}
+	}
+
+	for _, entry := range batch.Entries {
+		// CIE detail entries must be a debit
+		if entry.CreditOrDebit() != "C" {
+			msg := fmt.Sprintf(msgBatchTransactionCodeCredit, entry.TransactionCode)
+			return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: "TransactionCode", Msg: msg}
+		}
+
+		// Addenda validations - CIE Addenda must be Addenda05
+
+		// Addendum must be equal to 1
+		if len(entry.Addendum) > 1 {
+			return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: "Addendum", Msg: msgBatchCIEAddenda}
+		}
+
+		if len(entry.Addendum) > 0 {
+			// Addenda type assertion must be Addenda05
+			addenda05, ok := entry.Addendum[0].(*Addenda05)
+			if !ok {
+				msg := fmt.Sprintf(msgBatchCIEAddendaType, entry.Addendum[0])
+				return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: "Addendum", Msg: msg}
+			}
+
+			// Addenda05 must be Validated
+			if err := addenda05.Validate(); err != nil {
+				// convert the field error in to a batch error for a consistent api
+				if e, ok := err.(*FieldError); ok {
+					return &BatchError{BatchNumber: batch.Header.BatchNumber, FieldName: e.FieldName, Msg: e.Msg}
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// Create takes Batch Header and Entries and builds a valid batch
+func (batch *BatchCIE) Create() error {
+	// generates sequence numbers and batch control
+	if err := batch.build(); err != nil {
+		return err
+	}
+	// Additional steps specific to batch type
+	// ...
+	return batch.Validate()
+}


Test patch:
diff --git a/BatchARC_test.go b/BatchARC_test.go
index bb589d3b..914a5356 100644
--- a/BatchARC_test.go
+++ b/BatchARC_test.go
@@ -27,7 +27,7 @@ func mockARCEntryDetail() *EntryDetail {
 	entry.Amount = 25000
 	entry.SetCheckSerialNumber("123456789")
 	entry.SetReceivingCompany("ABC Company")
-	entry.SetTraceNumber(mockBatchARCHeader().ODFIIdentification, 123)
+	entry.SetTraceNumber(mockBatchARCHeader().ODFIIdentification, 1)
 	entry.Category = CategoryForward
 	return entry
 }
@@ -63,7 +63,7 @@ func mockARCEntryDetailCredit() *EntryDetail {
 	entry.Amount = 25000
 	entry.SetCheckSerialNumber("123456789")
 	entry.SetReceivingCompany("ABC Company")
-	entry.SetTraceNumber(mockBatchARCHeader().ODFIIdentification, 123)
+	entry.SetTraceNumber(mockBatchARCHeader().ODFIIdentification, 1)
 	entry.Category = CategoryForward
 	return entry
 }
diff --git a/batchBOC_test.go b/batchBOC_test.go
index c2d352a5..2eed0c32 100644
--- a/batchBOC_test.go
+++ b/batchBOC_test.go
@@ -27,7 +27,7 @@ func mockBOCEntryDetail() *EntryDetail {
 	entry.Amount = 25000
 	entry.SetCheckSerialNumber("123456789")
 	entry.SetReceivingCompany("ABC Company")
-	entry.SetTraceNumber(mockBatchBOCHeader().ODFIIdentification, 123)
+	entry.SetTraceNumber(mockBatchBOCHeader().ODFIIdentification, 1)
 	entry.Category = CategoryForward
 	return entry
 }
@@ -63,7 +63,7 @@ func mockBOCEntryDetailCredit() *EntryDetail {
 	entry.Amount = 25000
 	entry.SetCheckSerialNumber("123456789")
 	entry.SetReceivingCompany("ABC Company")
-	entry.SetTraceNumber(mockBatchBOCHeader().ODFIIdentification, 123)
+	entry.SetTraceNumber(mockBatchBOCHeader().ODFIIdentification, 1)
 	entry.Category = CategoryForward
 	return entry
 }
diff --git a/batchCIE_test.go b/batchCIE_test.go
new file mode 100644
index 00000000..73428191
--- /dev/null
+++ b/batchCIE_test.go
@@ -0,0 +1,436 @@
+// Copyright 2018 The ACH Authors
+// Use of this source code is governed by an Apache License
+// license that can be found in the LICENSE file.
+
+package ach
+
+import "testing"
+
+// mockBatchCIEHeader creates a BatchCIE BatchHeader
+func mockBatchCIEHeader() *BatchHeader {
+	bh := NewBatchHeader()
+	bh.ServiceClassCode = 220
+	bh.StandardEntryClassCode = "CIE"
+	bh.CompanyName = "Payee Name"
+	bh.CompanyIdentification = "121042882"
+	bh.CompanyEntryDescription = "ACH CIE"
+	bh.ODFIIdentification = "12104288"
+	return bh
+}
+
+// mockCIEEntryDetail creates a BatchCIE EntryDetail
+func mockCIEEntryDetail() *EntryDetail {
+	entry := NewEntryDetail()
+	entry.TransactionCode = 22
+	entry.SetRDFI("231380104")
+	entry.DFIAccountNumber = "744-5678-99"
+	entry.Amount = 25000
+	entry.IdentificationNumber = "45689033"
+	entry.IndividualName = "Wade Arnold"
+	entry.SetTraceNumber(mockBatchCIEHeader().ODFIIdentification, 1)
+	entry.DiscretionaryData = "01"
+	entry.Category = CategoryForward
+	return entry
+}
+
+// mockBatchCIE creates a BatchCIE
+func mockBatchCIE() *BatchCIE {
+	mockBatch := NewBatchCIE(mockBatchCIEHeader())
+	mockBatch.AddEntry(mockCIEEntryDetail())
+	mockBatch.GetEntries()[0].AddAddenda(mockAddenda05())
+	if err := mockBatch.Create(); err != nil {
+		panic(err)
+	}
+	return mockBatch
+}
+
+// testBatchCIEHeader creates a BatchCIE BatchHeader
+func testBatchCIEHeader(t testing.TB) {
+	batch, _ := NewBatch(mockBatchCIEHeader())
+	err, ok := batch.(*BatchCIE)
+	if !ok {
+		t.Errorf("Expecting BatchCIE got %T", err)
+	}
+}
+
+// TestBatchCIEHeader tests validating BatchCIE BatchHeader
+func TestBatchCIEHeader(t *testing.T) {
+	testBatchCIEHeader(t)
+}
+
+// BenchmarkBatchCIEHeader benchmarks validating BatchCIE BatchHeader
+func BenchmarkBatchCIEHeader(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEHeader(b)
+	}
+}
+
+// testBatchCIECreate validates BatchCIE create
+func testBatchCIECreate(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.Create()
+	if err := mockBatch.Validate(); err != nil {
+		t.Errorf("%T: %s", err, err)
+	}
+}
+
+// TestBatchCIECreate tests validating BatchCIE create
+func TestBatchCIECreate(t *testing.T) {
+	testBatchCIECreate(t)
+}
+
+// BenchmarkBatchCIECreate benchmarks validating BatchCIE create
+func BenchmarkBatchCIECreate(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIECreate(b)
+	}
+}
+
+// testBatchCIEStandardEntryClassCode validates BatchCIE create for an invalid StandardEntryClassCode
+func testBatchCIEStandardEntryClassCode(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.Header.StandardEntryClassCode = "WEB"
+	mockBatch.Create()
+	if err := mockBatch.Validate(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "StandardEntryClassCode" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIEStandardEntryClassCode tests validating BatchCIE create for an invalid StandardEntryClassCode
+func TestBatchCIEStandardEntryClassCode(t *testing.T) {
+	testBatchCIEStandardEntryClassCode(t)
+}
+
+// BenchmarkBatchCIEStandardEntryClassCode benchmarks validating BatchCIE create for an invalid StandardEntryClassCode
+func BenchmarkBatchCIEStandardEntryClassCode(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEStandardEntryClassCode(b)
+	}
+}
+
+// testBatchCIEServiceClassCodeEquality validates service class code equality
+func testBatchCIEServiceClassCodeEquality(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.GetControl().ServiceClassCode = 200
+	if err := mockBatch.Validate(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "ServiceClassCode" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIEServiceClassCodeEquality tests validating service class code equality
+func TestBatchCIEServiceClassCodeEquality(t *testing.T) {
+	testBatchCIEServiceClassCodeEquality(t)
+}
+
+// BenchmarkBatchCIEServiceClassCodeEquality benchmarks validating service class code equality
+func BenchmarkBatchCIEServiceClassCodeEquality(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEServiceClassCodeEquality(b)
+	}
+}
+
+// testBatchCIEServiceClass200 validates BatchCIE create for an invalid ServiceClassCode 200
+func testBatchCIEServiceClass200(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.Header.ServiceClassCode = 200
+	mockBatch.Create()
+	if err := mockBatch.Validate(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "ServiceClassCode" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIEServiceClass200 tests validating BatchCIE create for an invalid ServiceClassCode 200
+func TestBatchCIEServiceClass200(t *testing.T) {
+	testBatchCIEServiceClass200(t)
+}
+
+// BenchmarkBatchCIEServiceClass200 benchmarks validating BatchCIE create for an invalid ServiceClassCode 200
+func BenchmarkBatchCIEServiceClass200(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEServiceClass200(b)
+	}
+}
+
+// testBatchCIEServiceClass225 validates BatchCIE create for an invalid ServiceClassCode 225
+func testBatchCIEServiceClass225(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.Header.ServiceClassCode = 225
+	mockBatch.Create()
+	if err := mockBatch.Validate(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "ServiceClassCode" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIEServiceClass225 tests validating BatchCIE create for an invalid ServiceClassCode 225
+func TestBatchCIEServiceClass225(t *testing.T) {
+	testBatchCIEServiceClass225(t)
+}
+
+// BenchmarkBatchCIEServiceClass225 benchmarks validating BatchCIE create for an invalid ServiceClassCode 225
+func BenchmarkBatchCIEServiceClass225(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEServiceClass225(b)
+	}
+}
+
+// testBatchCIEServiceClass280 validates BatchCIE create for an invalid ServiceClassCode 280
+func testBatchCIEServiceClass280(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.Header.ServiceClassCode = 280
+	mockBatch.Create()
+	if err := mockBatch.Validate(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "ServiceClassCode" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIEServiceClass280 tests validating BatchCIE create for an invalid ServiceClassCode 280
+func TestBatchCIEServiceClass280(t *testing.T) {
+	testBatchCIEServiceClass280(t)
+}
+
+// BenchmarkBatchCIEServiceClass280 benchmarks validating BatchCIE create for an invalid ServiceClassCode 280
+func BenchmarkBatchCIEServiceClass280(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEServiceClass280(b)
+	}
+}
+
+// testBatchCIETransactionCode validates BatchCIE TransactionCode is not a debit
+func testBatchCIETransactionCode(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.GetEntries()[0].TransactionCode = 27
+	if err := mockBatch.Create(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "TransactionCode" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIETransactionCode tests validating BatchCIE TransactionCode is not a credit
+func TestBatchCIETransactionCode(t *testing.T) {
+	testBatchCIETransactionCode(t)
+}
+
+// BenchmarkBatchCIETransactionCode benchmarks validating BatchCIE TransactionCode is not a credit
+func BenchmarkBatchCIETransactionCode(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIETransactionCode(b)
+	}
+}
+
+// testBatchCIEAddendaCount validates BatchCIE Addendum count of 2
+func testBatchCIEAddendaCount(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.GetEntries()[0].AddAddenda(mockAddenda05())
+	mockBatch.Create()
+	if err := mockBatch.Validate(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "Addendum" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIEAddendaCount tests validating BatchCIE Addendum count of 2
+func TestBatchCIEAddendaCount(t *testing.T) {
+	testBatchCIEAddendaCount(t)
+}
+
+// BenchmarkBatchCIEAddendaCount benchmarks validating BatchCIE Addendum count of 2
+func BenchmarkBatchCIEAddendaCount(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEAddendaCount(b)
+	}
+}
+
+// testBatchCIEAddendaCountZero validates Addendum count of 0
+func testBatchCIEAddendaCountZero(t testing.TB) {
+	mockBatch := NewBatchCIE(mockBatchCIEHeader())
+	mockBatch.AddEntry(mockCIEEntryDetail())
+	if err := mockBatch.Create(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "Addendum" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIEAddendaCountZero tests validating Addendum count of 0
+func TestBatchCIEAddendaCountZero(t *testing.T) {
+	testBatchCIEAddendaCountZero(t)
+}
+
+// BenchmarkBatchCIEAddendaCountZero benchmarks validating Addendum count of 0
+func BenchmarkBatchCIEAddendaCountZero(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEAddendaCountZero(b)
+	}
+}
+
+// testBatchCIEInvalidAddendum validates Addendum must be Addenda05
+func testBatchCIEInvalidAddendum(t testing.TB) {
+	mockBatch := NewBatchCIE(mockBatchCIEHeader())
+	mockBatch.AddEntry(mockCIEEntryDetail())
+	mockBatch.GetEntries()[0].AddAddenda(mockAddenda02())
+	if err := mockBatch.Create(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "Addendum" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIEInvalidAddendum tests validating Addendum must be Addenda05
+func TestBatchCIEInvalidAddendum(t *testing.T) {
+	testBatchCIEInvalidAddendum(t)
+}
+
+// BenchmarkBatchCIEInvalidAddendum benchmarks validating Addendum must be Addenda05
+func BenchmarkBatchCIEInvalidAddendum(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEInvalidAddendum(b)
+	}
+}
+
+// testBatchCIEInvalidAddenda validates Addendum must be Addenda05 with record type 7
+func testBatchCIEInvalidAddenda(t testing.TB) {
+	mockBatch := NewBatchCIE(mockBatchCIEHeader())
+	mockBatch.AddEntry(mockCIEEntryDetail())
+	addenda05 := mockAddenda05()
+	addenda05.recordType = "63"
+	mockBatch.GetEntries()[0].AddAddenda(addenda05)
+	if err := mockBatch.Create(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "recordType" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIEInvalidAddenda tests validating Addendum must be Addenda05 with record type 7
+func TestBatchCIEInvalidAddenda(t *testing.T) {
+	testBatchCIEInvalidAddenda(t)
+}
+
+// BenchmarkBatchCIEInvalidAddenda benchmarks validating Addendum must be Addenda05 with record type 7
+func BenchmarkBatchCIEInvalidAddenda(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEInvalidAddenda(b)
+	}
+}
+
+// ToDo: Using a FieldError may need to add a BatchError and use *BatchError
+
+// testBatchCIEInvalidBuild validates an invalid batch build
+func testBatchCIEInvalidBuild(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.GetHeader().recordType = "3"
+	if err := mockBatch.Create(); err != nil {
+		if e, ok := err.(*FieldError); ok {
+			if e.FieldName != "recordType" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIEInvalidBuild tests validating an invalid batch build
+func TestBatchCIEInvalidBuild(t *testing.T) {
+	testBatchCIEInvalidBuild(t)
+}
+
+// BenchmarkBatchCIEInvalidBuild benchmarks validating an invalid batch build
+func BenchmarkBatchCIEInvalidBuild(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIEInvalidBuild(b)
+	}
+}
+
+// testBatchCIECardTransactionType validates BatchCIE create for an invalid CardTransactionType
+func testBatchCIECardTransactionType(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.GetEntries()[0].DiscretionaryData = "555"
+	if err := mockBatch.Validate(); err != nil {
+		if e, ok := err.(*BatchError); ok {
+			if e.FieldName != "CardTransactionType" {
+				t.Errorf("%T: %s", err, err)
+			}
+		} else {
+			t.Errorf("%T: %s", err, err)
+		}
+	}
+}
+
+// TestBatchCIECardTransactionType tests validating BatchCIE create for an invalid CardTransactionType
+func TestBatchCIECardTransactionType(t *testing.T) {
+	testBatchCIECardTransactionType(t)
+}
+
+// BenchmarkBatchCIECardTransactionType benchmarks validating BatchCIE create for an invalid CardTransactionType
+func BenchmarkBatchCIECardTransactionType(b *testing.B) {
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		testBatchCIECardTransactionType(b)
+	}
+}
diff --git a/batchPOP_test.go b/batchPOP_test.go
index f16e7218..54bc5779 100644
--- a/batchPOP_test.go
+++ b/batchPOP_test.go
@@ -29,7 +29,7 @@ func mockPOPEntryDetail() *EntryDetail {
 	entry.SetPOPTerminalCity("PHIL")
 	entry.SetPOPTerminalState("PA")
 	entry.SetReceivingCompany("ABC Company")
-	entry.SetTraceNumber(mockBatchPOPHeader().ODFIIdentification, 123)
+	entry.SetTraceNumber(mockBatchPOPHeader().ODFIIdentification, 1)
 	entry.Category = CategoryForward
 	return entry
 }
diff --git a/batchPOS_test.go b/batchPOS_test.go
index 69f377b0..06428f26 100644
--- a/batchPOS_test.go
+++ b/batchPOS_test.go
@@ -28,7 +28,7 @@ func mockPOSEntryDetail() *EntryDetail {
 	entry.IdentificationNumber = "45689033"
 	entry.IndividualName = "Wade Arnold"
 	//entry.SetReceivingCompany("ABC Company")
-	entry.SetTraceNumber(mockBatchPOSHeader().ODFIIdentification, 123)
+	entry.SetTraceNumber(mockBatchPOSHeader().ODFIIdentification, 1)
 	entry.DiscretionaryData = "01"
 	entry.Category = CategoryForward
 	return entry
diff --git a/batchRCK_test.go b/batchRCK_test.go
index ff7ccc71..52863ac7 100644
--- a/batchRCK_test.go
+++ b/batchRCK_test.go
@@ -27,7 +27,7 @@ func mockRCKEntryDetail() *EntryDetail {
 	entry.Amount = 2400
 	entry.SetCheckSerialNumber("123456789")
 	entry.IndividualName = "Wade Arnold"
-	entry.SetTraceNumber(mockBatchRCKHeader().ODFIIdentification, 123)
+	entry.SetTraceNumber(mockBatchRCKHeader().ODFIIdentification, 1)
 	entry.Category = CategoryForward
 	return entry
 }
@@ -63,7 +63,7 @@ func mockRCKEntryDetailCredit() *EntryDetail {
 	entry.Amount = 2400
 	entry.SetCheckSerialNumber("123456789")
 	entry.IndividualName = "Wade Arnold"
-	entry.SetTraceNumber(mockBatchRCKHeader().ODFIIdentification, 123)
+	entry.SetTraceNumber(mockBatchRCKHeader().ODFIIdentification, 1)
 	entry.Category = CategoryForward
 	return entry
 }
diff --git a/batchSHR_test.go b/batchSHR_test.go
index ac9bb1db..52649899 100644
--- a/batchSHR_test.go
+++ b/batchSHR_test.go
@@ -30,7 +30,7 @@ func mockSHREntryDetail() *EntryDetail {
 	entry.SetSHRCardExpirationDate("0722")
 	entry.SetSHRDocumentReferenceNumber("12345678910")
 	entry.SetSHRIndividualCardAccountNumber("1234567891123456789")
-	entry.SetTraceNumber(mockBatchSHRHeader().ODFIIdentification, 123)
+	entry.SetTraceNumber(mockBatchSHRHeader().ODFIIdentification, 1)
 	entry.DiscretionaryData = "01"
 	entry.Category = CategoryForward
 	return entry
diff --git a/batchTEL_test.go b/batchTEL_test.go
index b556edbf..d8aaaa33 100644
--- a/batchTEL_test.go
+++ b/batchTEL_test.go
@@ -25,7 +25,7 @@ func mockTELEntryDetail() *EntryDetail {
 	entry.Amount = 5000000
 	entry.IdentificationNumber = "Phone 333-2222"
 	entry.IndividualName = "Wade Arnold"
-	entry.SetTraceNumber(mockBatchTELHeader().ODFIIdentification, 123)
+	entry.SetTraceNumber(mockBatchTELHeader().ODFIIdentification, 1)
 	entry.SetPaymentType("S")
 	return entry
 }