Repository: moov-io/ach
Pull request #161 (2018-04-09 15:29:54)

Removing BatchParam


Patch:
diff --git a/batch.go b/batch.go
index fa59d57b..dae70d3a 100644
--- a/batch.go
+++ b/batch.go
@@ -18,22 +18,22 @@ type batch struct {
 	converters
 }
 
-// NewBatch takes a BatchParm and returns a matching SEC code batch type that is a batcher. Returns and error if the SEC code is not supported.
-func NewBatch(bp BatchParam) (Batcher, error) {
-	switch sec := bp.StandardEntryClass; sec {
+// 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 "PPD":
-		return NewBatchPPD(bp), nil
+		return NewBatchPPD(bh), nil
 	case "WEB":
-		return NewBatchWEB(bp), nil
+		return NewBatchWEB(bh), nil
 	case "CCD":
-		return NewBatchCCD(bp), nil
+		return NewBatchCCD(bh), nil
 	case "COR":
-		return NewBatchCOR(bp), nil
+		return NewBatchCOR(bh), nil
 	case "TEL":
-		return NewBatchTEL(bp), nil
+		return NewBatchTEL(bh), nil
 	default:
 	}
-	msg := fmt.Sprintf(msgFileNoneSEC, bp.StandardEntryClass)
+	msg := fmt.Sprintf(msgFileNoneSEC, bh.StandardEntryClassCode)
 	return nil, &FileError{FieldName: "StandardEntryClassCode", Msg: msg}
 }
 
diff --git a/batchCCD.go b/batchCCD.go
index 0e86a755..6c448646 100644
--- a/batchCCD.go
+++ b/batchCCD.go
@@ -12,18 +12,9 @@ type BatchCCD struct {
 }
 
 // NewBatchCCD returns a *BatchCCD
-func NewBatchCCD(params ...BatchParam) *BatchCCD {
+func NewBatchCCD(bh *BatchHeader) *BatchCCD {
 	batch := new(BatchCCD)
 	batch.SetControl(NewBatchControl())
-
-	if len(params) > 0 {
-		bh := NewBatchHeader(params[0])
-		bh.StandardEntryClassCode = "CCD"
-		batch.SetHeader(bh)
-		return batch
-	}
-	bh := NewBatchHeader()
-	bh.StandardEntryClassCode = "CCD"
 	batch.SetHeader(bh)
 	return batch
 }
diff --git a/batchCOR.go b/batchCOR.go
index 35a6979a..b5ce9001 100644
--- a/batchCOR.go
+++ b/batchCOR.go
@@ -16,18 +16,9 @@ var msgBatchCORAddenda = "found and 1 AddendaNOC is required for SEC Type COR"
 var msgBatchCORAddendaType = "%T found where AddendaNOC is required for SEC type NOC"
 
 // NewBatchCOR returns a *BatchCOR
-func NewBatchCOR(params ...BatchParam) *BatchCOR {
+func NewBatchCOR(bh *BatchHeader) *BatchCOR {
 	batch := new(BatchCOR)
 	batch.SetControl(NewBatchControl())
-
-	if len(params) > 0 {
-		bh := NewBatchHeader(params[0])
-		bh.StandardEntryClassCode = "COR"
-		batch.SetHeader(bh)
-		return batch
-	}
-	bh := NewBatchHeader()
-	bh.StandardEntryClassCode = "COR"
 	batch.SetHeader(bh)
 	return batch
 }
diff --git a/batchHeader.go b/batchHeader.go
index 8270a200..a96b0622 100644
--- a/batchHeader.go
+++ b/batchHeader.go
@@ -98,24 +98,13 @@ type BatchHeader struct {
 	converters
 }
 
-// NewBatchHeader returns a new BatchHeader with default values for none exported fields
-func NewBatchHeader(params ...BatchParam) *BatchHeader {
+// NewBatchHeader returns a new BatchHeader with default values for non exported fields
+func NewBatchHeader() *BatchHeader {
 	bh := &BatchHeader{
 		recordType:           "5",
 		OriginatorStatusCode: 0, //Prepared by an Originator
 		BatchNumber:          1,
 	}
-	if len(params) > 0 {
-		bh.ServiceClassCode = bh.parseNumField(params[0].ServiceClassCode)
-		bh.CompanyName = params[0].CompanyName
-		bh.CompanyIdentification = params[0].CompanyIdentification
-		bh.StandardEntryClassCode = params[0].StandardEntryClass
-		bh.CompanyEntryDescription = params[0].CompanyEntryDescription
-		bh.CompanyDescriptiveDate = params[0].CompanyDescriptiveDate
-		bh.EffectiveEntryDate = bh.parseSimpleDate(params[0].EffectiveEntryDate)
-		bh.ODFIIdentification = bh.parseNumField(params[0].ODFIIdentification)
-		return bh
-	}
 	return bh
 }
 
@@ -134,7 +123,7 @@ func (bh *BatchHeader) Parse(record string) {
 	bh.CompanyIdentification = strings.TrimSpace(record[40:50])
 	// 51-53 If the entries are PPD (credits/debits towards consumer account), use "PPD".
 	// If the entries are CCD (credits/debits towards corporate account), use "CCD".
-	// The difference between the 2 class codes are outside of the scope of this post, but generally most ACH transfers to consumer bank accounts should use "PPD"
+	// The difference between the 2 SEC codes are outside of the scope of this post.
 	bh.StandardEntryClassCode = record[50:53]
 	// 54-63 Your description of the transaction. This text will appear on the receivers’ bank statement.
 	// For example: "Payroll   "
@@ -279,18 +268,4 @@ func (bh *BatchHeader) BatchNumberField() string {
 
 func (bh *BatchHeader) settlementDateField() string {
 	return bh.alphaField(bh.settlementDate, 3)
-}
-
-// BatchParam returns a BatchParam with the values from BatchHeader
-func (bh *BatchHeader) BatchParam() BatchParam {
-	bp := BatchParam{
-		ServiceClassCode:        strconv.Itoa(bh.ServiceClassCode),
-		CompanyName:             bh.CompanyNameField(),
-		CompanyIdentification:   bh.CompanyIdentification,
-		StandardEntryClass:      bh.StandardEntryClassCode,
-		CompanyEntryDescription: bh.CompanyEntryDescription,
-		CompanyDescriptiveDate:  bh.CompanyDescriptiveDateField(),
-		EffectiveEntryDate:      bh.EffectiveEntryDateField(),
-		ODFIIdentification:      bh.ODFIIdentificationField()}
-	return bp
-}
+}
\ No newline at end of file
diff --git a/batchPPD.go b/batchPPD.go
index 852fa626..539d4ad0 100644
--- a/batchPPD.go
+++ b/batchPPD.go
@@ -10,18 +10,9 @@ type BatchPPD struct {
 }
 
 // NewBatchPPD returns a *BatchPPD
-func NewBatchPPD(params ...BatchParam) *BatchPPD {
+func NewBatchPPD(bh *BatchHeader) *BatchPPD {
 	batch := new(BatchPPD)
 	batch.SetControl(NewBatchControl())
-
-	if len(params) > 0 {
-		bh := NewBatchHeader(params[0])
-		bh.StandardEntryClassCode = ppd
-		batch.SetHeader(bh)
-		return batch
-	}
-	bh := NewBatchHeader()
-	bh.StandardEntryClassCode = ppd
 	batch.SetHeader(bh)
 	return batch
 }
diff --git a/batchParam.go b/batchParam.go
deleted file mode 100644
index 86ce7563..00000000
--- a/batchParam.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package ach
-
-// BatchParam contains information about the company(Originator) and the type of detail records to follow.
-// It is a subset of BatchHeader used for simplifying the client api build process.
-type BatchParam struct {
-	// ServiceClassCode a three digit code identifies:
-	// 	- 200 mixed debits and credits
-	// 	- 220 credits only
-	// 	- 225 debits only
-	ServiceClassCode string `json:"service_class_code"`
-	// CompanyName is the legal company name making the transaction.
-	CompanyName string `json:"company_name"`
-	// CompanyIdentification is assigned by your bank to identify your company. Frequently the federal tax ID
-	CompanyIdentification string `json:"company_identification"`
-	// StandardEntryClass identifies the payment type (product) found within the batch using a 3-character code
-	StandardEntryClass string `json:"standard_entry_class"`
-	// CompanyEntryDescription describes the transaction. For example "PAYROLL"
-	CompanyEntryDescription string `json:"company_entry_description"`
-	// CompanyDescriptiveDate a date chosen to identify the transactions in YYMMDD format.
-	CompanyDescriptiveDate string `json:"company_descriptive_date"`
-	// Date transactions are to be posted to the receivers’ account in YYMMDD format.
-	EffectiveEntryDate string `json:"effective_entry_date"`
-	// ODFIIdentification originating ODFI's routing number without the last digit
-	ODFIIdentification string `json:"ODFI_identification"`
-}
diff --git a/batchTEL.go b/batchTEL.go
index 6442f38b..50f92791 100644
--- a/batchTEL.go
+++ b/batchTEL.go
@@ -10,18 +10,9 @@ type BatchTEL struct {
 }
 
 // NewBatchTEL returns a *BatchTEL
-func NewBatchTEL(params ...BatchParam) *BatchTEL {
+func NewBatchTEL(bh *BatchHeader) *BatchTEL {
 	batch := new(BatchTEL)
 	batch.SetControl(NewBatchControl())
-
-	if len(params) > 0 {
-		bh := NewBatchHeader(params[0])
-		bh.StandardEntryClassCode = "TEL"
-		batch.SetHeader(bh)
-		return batch
-	}
-	bh := NewBatchHeader()
-	bh.StandardEntryClassCode = "TEL"
 	batch.SetHeader(bh)
 	return batch
 }
diff --git a/batchWeb.go b/batchWeb.go
index 571fec95..03cd232c 100644
--- a/batchWeb.go
+++ b/batchWeb.go
@@ -16,18 +16,9 @@ var (
 )
 
 // NewBatchWEB returns a *BatchWEB
-func NewBatchWEB(params ...BatchParam) *BatchWEB {
+func NewBatchWEB(bh *BatchHeader) *BatchWEB {
 	batch := new(BatchWEB)
 	batch.SetControl(NewBatchControl())
-
-	if len(params) > 0 {
-		bh := NewBatchHeader(params[0])
-		bh.StandardEntryClassCode = "WEB"
-		batch.SetHeader(bh)
-		return batch
-	}
-	bh := NewBatchHeader()
-	bh.StandardEntryClassCode = "WEB"
 	batch.SetHeader(bh)
 	return batch
 }
diff --git a/example/ach-ppd-write/main.go b/example/ach-ppd-write/main.go
index 4596226c..42d964ca 100644
--- a/example/ach-ppd-write/main.go
+++ b/example/ach-ppd-write/main.go
@@ -43,8 +43,7 @@ func main() {
 	entry.IndividualName = "Receiver Account Name" // Identifies the receiver of the transaction
 
 	// build the batch
-	batch := ach.NewBatchPPD()
-	batch.SetHeader(bh)
+	batch := ach.NewBatchPPD(bh)
 	batch.AddEntry(entry)
 	if err := batch.Create(); err != nil {
 		log.Fatalf("Unexpected error building batch: %s\n", err)
diff --git a/example/simple-file-creation/main.go b/example/simple-file-creation/main.go
index a8a23472..4b57ea9f 100644
--- a/example/simple-file-creation/main.go
+++ b/example/simple-file-creation/main.go
@@ -5,6 +5,8 @@ import (
 	"os"
 
 	"github.com/moov-io/ach"
+	"strconv"
+	"time"
 )
 
 func main() {
@@ -18,14 +20,16 @@ func main() {
 
 	// To create a batch.
 	// Errors only if payment type is not supported.
-	batch, _ := ach.NewBatch(ach.BatchParam{
-		ServiceClassCode:        "200",
-		CompanyName:             "Your Company",
-		StandardEntryClass:      "PPD",
-		CompanyIdentification:   "123456789",
-		CompanyEntryDescription: "Trans. Description",
-		CompanyDescriptiveDate:  "Oct 23",
-		ODFIIdentification:      "123456789"})
+	bh := ach.NewBatchHeader()
+	bh.ServiceClassCode = 200
+	bh.CompanyName = "Your Company"
+	bh.CompanyIdentification = strconv.Itoa(file.Header.ImmediateOrigin)
+	bh.StandardEntryClassCode = "PPD"
+	bh.CompanyEntryDescription = "Trans. Description"
+	bh.EffectiveEntryDate = time.Now().AddDate(0, 0, 1)
+	bh.ODFIIdentification = 123456789
+
+	batch, _ := ach.NewBatch(bh)
 
 	// To create an entry
 	entry := ach.NewEntryDetail(ach.EntryParam{
@@ -58,14 +62,16 @@ func main() {
 
 	// Now add a new batch for accepting payments on the web
 
-	batch2, _ := ach.NewBatch(ach.BatchParam{
-		ServiceClassCode:        "220",
-		CompanyName:             "Your Company",
-		StandardEntryClass:      "WEB",
-		CompanyIdentification:   "123456789",
-		CompanyEntryDescription: "subscr",
-		CompanyDescriptiveDate:  "Oct 23",
-		ODFIIdentification:      "123456789"})
+	bh2 := ach.NewBatchHeader()
+	bh2.ServiceClassCode = 220
+	bh2.CompanyName = "Your Company"
+	bh2.CompanyIdentification = strconv.Itoa(file.Header.ImmediateOrigin)
+	bh2.StandardEntryClassCode = "WEB"
+	bh2.CompanyEntryDescription = "Subscr"
+	bh2.EffectiveEntryDate = time.Now().AddDate(0, 0, 1)
+	bh2.ODFIIdentification = 123456789
+
+	batch2, _ := ach.NewBatch(bh2)
 
 	// Add an entry and define if it is a single or reoccuring payment
 	// The following is a reoccuring payment for $7.99
@@ -106,3 +112,5 @@ func main() {
 	}
 	w.Flush()
 }
+
+
diff --git a/reader.go b/reader.go
index af675dc7..ca22e9fe 100644
--- a/reader.go
+++ b/reader.go
@@ -195,12 +195,11 @@ func (r *Reader) parseBatchHeader() error {
 	}
 
 	// Passing SEC type into NewBatch creates a Batcher of SEC code type.
-	batch, err := NewBatch(bh.BatchParam())
+	batch, err := NewBatch(bh)
 	if err != nil {
 		return r.error(err)
 	}
 
-	batch.SetHeader(bh)
 	r.addCurrentBatch(batch)
 	return nil
 }


Test patch:
diff --git a/addenda_internal_test.go b/addenda_internal_test.go
index ac5f9437..2daa8051 100644
--- a/addenda_internal_test.go
+++ b/addenda_internal_test.go
@@ -33,8 +33,8 @@ func TestParseAddenda(t *testing.T) {
 	var line = "705WEB                                        DIEGO MAY                            00010000001"
 
 	r := NewReader(strings.NewReader(line))
-	r.addCurrentBatch(NewBatchPPD())
-	r.currentBatch.GetHeader().StandardEntryClassCode = "PPD"
+	r.addCurrentBatch(NewBatchPPD(mockBatchPPDHeader()))
+	//r.currentBatch.GetHeader().StandardEntryClassCode = "PPD"
 	r.currentBatch.AddEntry(&EntryDetail{TransactionCode: 22, AddendaRecordIndicator: 1})
 	r.line = line
 	err := r.parseAddenda()
@@ -64,7 +64,7 @@ func TestParseAddenda(t *testing.T) {
 func TestAddendaString(t *testing.T) {
 	var line = "705WEB                                        DIEGO MAY                            00010000001"
 	r := NewReader(strings.NewReader(line))
-	r.addCurrentBatch(NewBatchPPD())
+	r.addCurrentBatch(NewBatchPPD(mockBatchPPDHeader()))
 	r.currentBatch.GetHeader().StandardEntryClassCode = "PPD"
 	r.currentBatch.AddEntry(&EntryDetail{AddendaRecordIndicator: 1})
 	r.line = line
diff --git a/batchCCD_test.go b/batchCCD_test.go
index d28bbc4b..e71bb5f2 100644
--- a/batchCCD_test.go
+++ b/batchCCD_test.go
@@ -29,8 +29,7 @@ func mockCCDEntryDetail() *EntryDetail {
 }
 
 func mockBatchCCD() *BatchCCD {
-	mockBatch := NewBatchCCD()
-	mockBatch.SetHeader(mockBatchCCDHeader())
+	mockBatch := NewBatchCCD(mockBatchCCDHeader())
 	mockBatch.AddEntry(mockCCDEntryDetail())
 	mockBatch.GetEntries()[0].AddAddenda(mockAddenda())
 	if err := mockBatch.Create(); err != nil {
@@ -39,6 +38,16 @@ func mockBatchCCD() *BatchCCD {
 	return mockBatch
 }
 
+// Test Batch Header
+func TestBatchCCDHeader(t *testing.T) {
+	batch, _ := NewBatch(mockBatchCCDHeader())
+
+	_, ok := batch.(*BatchCCD)
+	if !ok {
+		t.Error("Expecting BatchCCD")
+	}
+}
+
 // A Batch CCD can only have one addendum per entry detail
 func TestBatchCCDAddendumCount(t *testing.T) {
 	mockBatch := mockBatchCCD()
@@ -131,21 +140,3 @@ func TestBatchCCDCreate(t *testing.T) {
 		}
 	}
 }
-
-func TestBatchCCDParam(t *testing.T) {
-
-	batch, _ := NewBatch(BatchParam{
-		ServiceClassCode:        "220",
-		CompanyName:             "Your Company, inc",
-		StandardEntryClass:      "CCD",
-		CompanyIdentification:   "123456789",
-		CompanyEntryDescription: "Vndr Pay",
-		CompanyDescriptiveDate:  "Oct 23",
-		ODFIIdentification:      "123456789"})
-
-	_, ok := batch.(*BatchCCD)
-	if !ok {
-		t.Error("Expecting BachCCD")
-	}
-
-}
diff --git a/batchCOR_test.go b/batchCOR_test.go
index 517e253d..bfd35b49 100644
--- a/batchCOR_test.go
+++ b/batchCOR_test.go
@@ -31,8 +31,7 @@ func mockCOREntryDetail() *EntryDetail {
 }
 
 func mockBatchCOR() *BatchCOR {
-	mockBatch := NewBatchCOR()
-	mockBatch.SetHeader(mockBatchCORHeader())
+	mockBatch := NewBatchCOR(mockBatchCORHeader())
 	mockBatch.AddEntry(mockCOREntryDetail())
 	mockBatch.GetEntries()[0].AddAddenda(mockAddendaNOC())
 	if err := mockBatch.Create(); err != nil {
@@ -41,6 +40,16 @@ func mockBatchCOR() *BatchCOR {
 	return mockBatch
 }
 
+// Test Batch Header
+func TestBatchCORHeader(t *testing.T) {
+	batch, _ := NewBatch(mockBatchCORHeader())
+
+	_, ok := batch.(*BatchCOR)
+	if !ok {
+		t.Error("Expecting BachCOR")
+	}
+}
+
 func TestBatchCORSEC(t *testing.T) {
 	mockBatch := mockBatchCOR()
 	mockBatch.header.StandardEntryClassCode = "RCK"
@@ -55,23 +64,6 @@ func TestBatchCORSEC(t *testing.T) {
 	}
 }
 
-func TestBatchCORParam(t *testing.T) {
-
-	batch, _ := NewBatch(BatchParam{
-		ServiceClassCode:        "220",
-		CompanyName:             "Your Company, inc",
-		StandardEntryClass:      "COR",
-		CompanyIdentification:   "123456789",
-		CompanyEntryDescription: "Vndr Pay",
-		CompanyDescriptiveDate:  "Oct 23",
-		ODFIIdentification:      "123456789"})
-
-	_, ok := batch.(*BatchCOR)
-	if !ok {
-		t.Error("Expecting BachCOR")
-	}
-}
-
 func TestBatchCORAddendumCountTwo(t *testing.T) {
 	mockBatch := mockBatchCOR()
 	// Adding a second addenda to the mock entry
@@ -90,8 +82,7 @@ func TestBatchCORAddendumCountTwo(t *testing.T) {
 }
 
 func TestBatchCORAddendaCountZero(t *testing.T) {
-	mockBatch := NewBatchCOR()
-	mockBatch.SetHeader(mockBatchCORHeader())
+	mockBatch := NewBatchCOR(mockBatchCORHeader())
 	mockBatch.AddEntry(mockCOREntryDetail())
 	if err := mockBatch.Create(); err != nil {
 		if e, ok := err.(*BatchError); ok {
@@ -106,8 +97,7 @@ func TestBatchCORAddendaCountZero(t *testing.T) {
 
 // check that Addendum is of type AddendaNOC
 func TestBatchCORAddendaType(t *testing.T) {
-	mockBatch := NewBatchCOR()
-	mockBatch.SetHeader(mockBatchCORHeader())
+	mockBatch := NewBatchCOR(mockBatchCORHeader())
 	mockBatch.AddEntry(mockCOREntryDetail())
 	mockBatch.GetEntries()[0].AddAddenda(mockAddenda())
 	if err := mockBatch.Create(); err != nil {
diff --git a/batchControl_internal_test.go b/batchControl_internal_test.go
index 389b527d..e6fa7cbf 100644
--- a/batchControl_internal_test.go
+++ b/batchControl_internal_test.go
@@ -38,12 +38,11 @@ func TestParseBatchControl(t *testing.T) {
 	var line = "82250000010005320001000000010500000000000000origid                             076401250000001"
 	r := NewReader(strings.NewReader(line))
 	r.line = line
-	r.addCurrentBatch(NewBatchPPD())
 	bh := BatchHeader{BatchNumber: 1,
 		ServiceClassCode:      225,
 		CompanyIdentification: "origid",
 		ODFIIdentification:    7640125}
-	r.currentBatch.SetHeader(&bh)
+	r.addCurrentBatch(NewBatchPPD(&bh))
 
 	r.currentBatch.AddEntry(&EntryDetail{TransactionCode: 27, Amount: 10500, RDFIIdentification: 5320001, TraceNumber: 76401255655291})
 	if err := r.parseBatchControl(); err != nil {
@@ -91,12 +90,11 @@ func TestBCString(t *testing.T) {
 	var line = "82250000010005320001000000010500000000000000origid                             076401250000001"
 	r := NewReader(strings.NewReader(line))
 	r.line = line
-	r.addCurrentBatch(NewBatchPPD())
 	bh := BatchHeader{BatchNumber: 1,
 		ServiceClassCode:      225,
 		CompanyIdentification: "origid",
 		ODFIIdentification:    7640125}
-	r.currentBatch.SetHeader(&bh)
+	r.addCurrentBatch(NewBatchPPD(&bh))
 
 	r.currentBatch.AddEntry(&EntryDetail{TransactionCode: 27, Amount: 10500, RDFIIdentification: 5320001, TraceNumber: 76401255655291})
 	if err := r.parseBatchControl(); err != nil {
diff --git a/batchHeader_internal_test.go b/batchHeader_internal_test.go
index fd4fa1a0..cab77c8a 100644
--- a/batchHeader_internal_test.go
+++ b/batchHeader_internal_test.go
@@ -294,30 +294,3 @@ func TestBHFieldInclusionOriginatorStatusCode(t *testing.T) {
 		}
 	}
 }
-
-func TestBHtoBatchParam(t *testing.T) {
-	bh := mockBatchHeader()
-	bp := bh.BatchParam()
-
-	if bh.ServiceClassCode != bh.parseNumField(bp.ServiceClassCode) {
-		t.Errorf("ServiceClassCode Expected '%b' got: %s", bh.ServiceClassCode, bp.ServiceClassCode)
-	}
-	if bh.CompanyName != bp.CompanyName {
-		t.Errorf("CompanyName Expected '%s' got: %s", bh.CompanyName, bp.CompanyName)
-	}
-	if bh.StandardEntryClassCode != bp.StandardEntryClass {
-		t.Errorf("StandardEntryClass Expected '%s' got: %s", bh.StandardEntryClassCode, bp.StandardEntryClass)
-	}
-	if bh.CompanyIdentification != bp.CompanyIdentification {
-		t.Errorf("CompanyIdentification Expected '%s' got: %s", bh.CompanyIdentification, bp.CompanyIdentification)
-	}
-	if bh.CompanyEntryDescription != bp.CompanyEntryDescription {
-		t.Errorf("CompanyEntryDescription Expected '%s' got: %s", bh.CompanyEntryDescription, bp.CompanyEntryDescription)
-	}
-	if bh.CompanyDescriptiveDateField() != bp.CompanyDescriptiveDate {
-		t.Errorf("CompanyDescriptiveDate Expected '%s' got: %s", bh.CompanyDescriptiveDateField(), bp.CompanyDescriptiveDate)
-	}
-	if bh.ODFIIdentification != bh.parseNumField(bp.ODFIIdentification) {
-		t.Errorf("ODFIIdentification Expected '%b' got: %s", bh.ODFIIdentification, bp.ODFIIdentification)
-	}
-}
diff --git a/batchPPD_test.go b/batchPPD_test.go
index f3e4e311..510d923d 100644
--- a/batchPPD_test.go
+++ b/batchPPD_test.go
@@ -9,10 +9,35 @@ import (
 	"time"
 )
 
+
+func mockBatchPPDHeader() *BatchHeader {
+	bh := NewBatchHeader()
+	bh.ServiceClassCode = 220
+	bh.StandardEntryClassCode = "PPD"
+	bh.CompanyName = "ACME Corporation"
+	bh.CompanyIdentification = "123456789"
+	bh.CompanyEntryDescription = "PAYROLL"
+	bh.EffectiveEntryDate = time.Now()
+	bh.ODFIIdentification = 6200001
+	return bh
+}
+
+func mockPPDEntryDetail() *EntryDetail {
+	entry := NewEntryDetail()
+	entry.TransactionCode = 22
+	entry.SetRDFI(9101298)
+	entry.DFIAccountNumber = "123456789"
+	entry.Amount = 100000000
+	entry.IndividualName = "Wade Arnold"
+	entry.setTraceNumber(mockBatchPPDHeader().ODFIIdentification, 1)
+	//entry.setTraceNumber(6200001, 1)
+	entry.Category = CategoryForward
+	return entry
+}
+
 func mockBatchPPD() *BatchPPD {
-	mockBatch := NewBatchPPD()
-	mockBatch.SetHeader(mockBatchHeader())
-	mockBatch.AddEntry(mockEntryDetail())
+	mockBatch := NewBatchPPD(mockBatchPPDHeader())
+	mockBatch.AddEntry(mockPPDEntryDetail())
 	if err := mockBatch.Create(); err != nil {
 		panic(err)
 	}
@@ -103,7 +128,6 @@ func TestBatchODFIIDMismatch(t *testing.T) {
 }
 
 func TestBatchBuild(t *testing.T) {
-	mockBatch := NewBatchPPD()
 	header := NewBatchHeader()
 	header.ServiceClassCode = 200
 	header.CompanyName = "MY BEST COMP."
@@ -113,11 +137,12 @@ func TestBatchBuild(t *testing.T) {
 	header.CompanyEntryDescription = "PAYROLL"
 	header.EffectiveEntryDate = time.Now()
 	header.ODFIIdentification = 109991234
-	mockBatch.SetHeader(header)
+
+	mockBatch := NewBatchPPD(mockBatchPPDHeader())
 
 	entry := NewEntryDetail()
 	entry.TransactionCode = 22                  // ACH Credit
-	entry.SetRDFI(81086674)                     // scottrade bank routing number
+	entry.SetRDFI(81086674)                // scottrade bank routing number
 	entry.DFIAccountNumber = "62292250"         // scottrade account number
 	entry.Amount = 1000000                      // 1k dollars
 	entry.IdentificationNumber = "658-888-2468" // Unique ID for payment
diff --git a/batchTEL_test.go b/batchTEL_test.go
index 5f4edc24..b3a24584 100644
--- a/batchTEL_test.go
+++ b/batchTEL_test.go
@@ -29,8 +29,7 @@ func mockTELEntryDetail() *EntryDetail {
 }
 
 func mockBatchTEL() *BatchTEL {
-	mockBatch := NewBatchTEL()
-	mockBatch.SetHeader(mockBatchTELHeader())
+	mockBatch := NewBatchTEL(mockBatchTELHeader())
 	mockBatch.AddEntry(mockTELEntryDetail())
 	if err := mockBatch.Create(); err != nil {
 		panic(err)
@@ -38,8 +37,8 @@ func mockBatchTEL() *BatchTEL {
 	return mockBatch
 }
 
-func TestBatchTELParam(t *testing.T) {
-	batch, _ := NewBatch(mockBatchTELHeader().BatchParam())
+func TestBatchTELHeader(t *testing.T) {
+	batch, _ := NewBatch(mockBatchTELHeader())
 	err, ok := batch.(*BatchTEL)
 	if !ok {
 		t.Errorf("Expecting BatchTEL got %T", err)
diff --git a/batchWEB_test.go b/batchWEB_test.go
index 3692a7ba..d80ceb0a 100644
--- a/batchWEB_test.go
+++ b/batchWEB_test.go
@@ -26,8 +26,7 @@ func mockWEBEntryDetail() *EntryDetail {
 }
 
 func mockBatchWEB() *BatchWEB {
-	mockBatch := NewBatchWEB()
-	mockBatch.SetHeader(mockBatchWEBHeader())
+	mockBatch := NewBatchWEB(mockBatchWEBHeader())
 	mockBatch.AddEntry(mockWEBEntryDetail())
 	mockBatch.GetEntries()[0].AddAddenda(mockAddenda())
 	if err := mockBatch.Create(); err != nil {
@@ -37,6 +36,7 @@ func mockBatchWEB() *BatchWEB {
 }
 
 // No more than 1 batch per entry detail record can exist
+// No more than 1 addenda record per entry detail record can exist
 func TestBatchWebAddenda(t *testing.T) {
 	mockBatch := mockBatchWEB()
 	// mock batch already has one addenda. Creating two addenda should error
diff --git a/batch_test.go b/batch_test.go
index 40608765..4c137245 100644
--- a/batch_test.go
+++ b/batch_test.go
@@ -2,6 +2,7 @@ package ach
 
 import (
 	"testing"
+	"time"
 )
 
 // batch should never be used directly.
@@ -15,6 +16,19 @@ func mockBatch() *batch {
 	return mockBatch
 }
 
+// Invalid SEC CODE Batch Header
+func mockBatchInvalidSECHeader() *BatchHeader {
+	bh := NewBatchHeader()
+	bh.ServiceClassCode = 220
+	bh.StandardEntryClassCode = "NIL"
+	bh.CompanyName = "ACME Corporation"
+	bh.CompanyIdentification = "123456789"
+	bh.CompanyEntryDescription = "PAYROLL"
+	bh.EffectiveEntryDate = time.Now()
+	bh.ODFIIdentification = 6200001
+	return bh
+}
+
 // Test cases that apply to all batch types
 
 func TestBatchNumberMismatch(t *testing.T) {
@@ -231,9 +245,9 @@ func TestBatchAddendaTraceNumber(t *testing.T) {
 	}
 }
 
+
 func TestNewBatchDefault(t *testing.T) {
-	_, err := NewBatch(BatchParam{
-		StandardEntryClass: "NIL"})
+	_, err := NewBatch(mockBatchInvalidSECHeader())
 
 	if e, ok := err.(*FileError); ok {
 		if e.FieldName != "StandardEntryClassCode" {
@@ -244,6 +258,8 @@ func TestNewBatchDefault(t *testing.T) {
 	}
 }
 
+
+
 func TestBatchCategory(t *testing.T) {
 	mockBatch := mockBatch()
 	// Add a Addenda Return to the mock batch
diff --git a/entryDetail_internal_test.go b/entryDetail_internal_test.go
index e4afd1c1..600a21ad 100644
--- a/entryDetail_internal_test.go
+++ b/entryDetail_internal_test.go
@@ -47,7 +47,7 @@ func TestMockEntryDetail(t *testing.T) {
 func TestParseEntryDetail(t *testing.T) {
 	var line = "62705320001912345            0000010500c-1            Arnold Wade           DD0076401255655291"
 	r := NewReader(strings.NewReader(line))
-	r.addCurrentBatch(NewBatchPPD())
+	r.addCurrentBatch(NewBatchPPD(mockBatchPPDHeader()))
 	r.currentBatch.SetHeader(mockBatchHeader())
 	r.line = line
 	if err := r.parseEntryDetail(); err != nil {
@@ -95,7 +95,7 @@ func TestParseEntryDetail(t *testing.T) {
 func TestEDString(t *testing.T) {
 	var line = "62705320001912345            0000010500c-1            Arnold Wade           DD0076401255655291"
 	r := NewReader(strings.NewReader(line))
-	r.addCurrentBatch(NewBatchPPD())
+	r.addCurrentBatch(NewBatchPPD(mockBatchPPDHeader()))
 	r.currentBatch.SetHeader(mockBatchHeader())
 	r.line = line
 	if err := r.parseEntryDetail(); err != nil {
diff --git a/file_test.go b/file_test.go
index 721e1131..83cd8200 100644
--- a/file_test.go
+++ b/file_test.go
@@ -109,8 +109,7 @@ func TestFileEntryHash(t *testing.T) {
 
 func TestFileBlockCount10(t *testing.T) {
 	file := NewFile().SetHeader(mockFileHeader())
-	batch := NewBatchPPD()
-	batch.SetHeader(mockBatchHeader())
+	batch := NewBatchPPD(mockBatchPPDHeader())
 	batch.AddEntry(mockEntryDetail())
 	batch.AddEntry(mockEntryDetail())
 	batch.AddEntry(mockEntryDetail())
@@ -185,7 +184,10 @@ func TestFileReturnEntries(t *testing.T) {
 	// create or copy the previous batch header of the item being returned
 	batchHeader := mockBatchHeader()
 	// create or copy the batch to be returned
-	batch, err := NewBatch(BatchParam{StandardEntryClass: batchHeader.StandardEntryClassCode})
+
+	//batch, err := NewBatch(BatchParam{StandardEntryClass: batchHeader.StandardEntryClassCode})
+	batch, err := NewBatch(batchHeader)
+
 	if err != nil {
 		t.Error(err.Error())
 	}
diff --git a/reader_test.go b/reader_test.go
index 10d16db3..40fa398c 100644
--- a/reader_test.go
+++ b/reader_test.go
@@ -104,7 +104,7 @@ func TestTwoFileControls(t *testing.T) {
 	var line = "9000001000001000000010005320001000000010500000000000000                                       "
 	var twoControls = line + "\n" + line
 	r := NewReader(strings.NewReader(twoControls))
-	r.addCurrentBatch(NewBatchPPD())
+	r.addCurrentBatch(NewBatchPPD(mockBatchPPDHeader()))
 	bc := BatchControl{EntryAddendaCount: 1,
 		TotalDebitEntryDollarAmount: 10500,
 		EntryHash:                   5320001}
@@ -193,10 +193,10 @@ func TestFileBatchHeaderErr(t *testing.T) {
 // TestFileBatchHeaderErr Error when two batch headers exists in a current batch
 func TestFileBatchHeaderDuplicate(t *testing.T) {
 	// create a new Batch header string
-	bh := mockBatchHeader()
+	bh := mockBatchPPDHeader()
 	r := NewReader(strings.NewReader(bh.String()))
 	// instantitate a batch header in the reader
-	r.addCurrentBatch(NewBatchPPD())
+	r.addCurrentBatch(NewBatchPPD(bh))
 	// read should fail because it is parsing a second batch header and there can only be one.
 	_, err := r.Read()
 	if p, ok := err.(*ParseError); ok {
@@ -232,7 +232,7 @@ func TestFileEntryDetail(t *testing.T) {
 	ed.TransactionCode = 0
 	line := ed.String()
 	r := NewReader(strings.NewReader(line))
-	r.addCurrentBatch(NewBatchPPD())
+	r.addCurrentBatch(NewBatchPPD(mockBatchPPDHeader()))
 	r.currentBatch.SetHeader(mockBatchHeader())
 	_, err := r.Read()
 	if p, ok := err.(*ParseError); ok {
diff --git a/recordParams_test.go b/recordParams_test.go
index bd6d1bc2..aa21c8c2 100644
--- a/recordParams_test.go
+++ b/recordParams_test.go
@@ -1,8 +1,8 @@
 package ach
 
 import (
-	"bytes"
 	"testing"
+	"bytes"
 )
 
 func TestFileParam(t *testing.T) {
@@ -22,24 +22,20 @@ func TestFileParam(t *testing.T) {
 	}
 }
 
+
 func TestBatchParam(t *testing.T) {
-	companyName := "Your Company"
-	batch := NewBatchPPD(BatchParam{
-		ServiceClassCode:        "220",
-		CompanyName:             companyName,
-		StandardEntryClass:      "PPD",
-		CompanyIdentification:   "123456789",
-		CompanyEntryDescription: "Trans. Description",
-		CompanyDescriptiveDate:  "Oct 23",
-		ODFIIdentification:      "123456789"})
-
-	if err := batch.header.Validate(); err != nil {
+	companyName := "ACME Corporation"
+	batch, _ := NewBatch(mockBatchPPDHeader())
+
+	bh := batch.GetHeader()
+	if err := bh.Validate(); err != nil {
 		t.Errorf("%T: %s", err, err)
 	}
-	if batch.header.CompanyName != companyName {
+	if bh.CompanyName != companyName {
 		t.Errorf("BatchParam value was not copied to batch.header.CompanyName")
 	}
 }
+
 func TestEntryParam(t *testing.T) {
 	entry := NewEntryDetail(EntryParam{
 		ReceivingDFI:      "102001017",
@@ -103,14 +99,7 @@ func TestBuildFileParam(t *testing.T) {
 		ReferenceCode:            "#00000A1"})
 
 	// To create a batch. Errors only if payment type is not supported.
-	batch, _ := NewBatch(BatchParam{
-		ServiceClassCode:        "225",
-		CompanyName:             "Your Company",
-		StandardEntryClass:      "PPD",
-		CompanyIdentification:   "123456789",
-		CompanyEntryDescription: "Trans. Description",
-		CompanyDescriptiveDate:  "Oct 23",
-		ODFIIdentification:      "12345678"})
+	batch, _ := NewBatch(mockBatchHeader())
 
 	// To create an entry
 	entry := NewEntryDetail(EntryParam{
@@ -144,14 +133,7 @@ func TestBuildFileParam(t *testing.T) {
 
 	// Now add a new batch for accepting payments on the web
 
-	batch, _ = NewBatch(BatchParam{
-		ServiceClassCode:        "220",
-		CompanyName:             "Your Company",
-		StandardEntryClass:      "WEB",
-		CompanyIdentification:   "123456789",
-		CompanyEntryDescription: "monthly subscription",
-		CompanyDescriptiveDate:  "Oct 23",
-		ODFIIdentification:      "123456789"})
+	batch, _ = NewBatch(mockBatchWEBHeader())
 
 	// Add an entry and define if it is a single or reoccuring payment
 	// The following is a reoccuring payment for $7.99
diff --git a/writer_test.go b/writer_test.go
index 2ea8120b..bb5d934d 100644
--- a/writer_test.go
+++ b/writer_test.go
@@ -10,7 +10,7 @@ func TestPPDWrite(t *testing.T) {
 	file := NewFile().SetHeader(mockFileHeader())
 	entry := mockEntryDetail()
 	entry.AddAddenda(mockAddenda())
-	batch := NewBatchPPD()
+	batch := NewBatchPPD(mockBatchPPDHeader())
 	batch.SetHeader(mockBatchHeader())
 	batch.AddEntry(entry)
 	batch.Create()