Repository: moov-io/ach
Pull request #1075 (2022-08-29 09:52:46)

Changing the ServiceClassCode validation for ARC, BOC, CIE, POP, RCK, T…
…RC, TRC, XCK

Fixes: https://github.com/moov-io/ach/issues/1072 


Patch:
diff --git a/batchARC.go b/batchARC.go
index 239411b8..5372973b 100644
--- a/batchARC.go
+++ b/batchARC.go
@@ -60,7 +60,7 @@ func (batch *BatchARC) Validate() error {
 
 	// ARC detail entries can only be a debit, ServiceClassCode must allow debits
 	switch batch.Header.ServiceClassCode {
-	case MixedDebitsAndCredits, CreditsOnly:
+	case CreditsOnly:
 		return batch.Error("ServiceClassCode", ErrBatchServiceClassCode, batch.Header.ServiceClassCode)
 	}
 
diff --git a/batchBOC.go b/batchBOC.go
index 919ee646..4d7a55ff 100644
--- a/batchBOC.go
+++ b/batchBOC.go
@@ -65,7 +65,7 @@ func (batch *BatchBOC) Validate() error {
 
 	// BOC detail entries can only be a debit, ServiceClassCode must allow debits
 	switch batch.Header.ServiceClassCode {
-	case MixedDebitsAndCredits, CreditsOnly:
+	case CreditsOnly:
 		return batch.Error("ServiceClassCode", ErrBatchServiceClassCode, batch.Header.ServiceClassCode)
 	}
 
diff --git a/batchCIE.go b/batchCIE.go
index e8c790f1..6ac52ac1 100644
--- a/batchCIE.go
+++ b/batchCIE.go
@@ -58,7 +58,7 @@ func (batch *BatchCIE) Validate() error {
 
 	// CIE detail entries can only be a credit, ServiceClassCode must allow credit
 	switch batch.Header.ServiceClassCode {
-	case MixedDebitsAndCredits, DebitsOnly:
+	case DebitsOnly:
 		return batch.Error("ServiceClassCode", ErrBatchServiceClassCode, batch.Header.ServiceClassCode)
 	}
 
diff --git a/batchPOP.go b/batchPOP.go
index 9b1bd408..a007a339 100644
--- a/batchPOP.go
+++ b/batchPOP.go
@@ -62,7 +62,7 @@ func (batch *BatchPOP) Validate() error {
 
 	// POP detail entries can only be a debit, ServiceClassCode must allow debits
 	switch batch.Header.ServiceClassCode {
-	case MixedDebitsAndCredits, CreditsOnly:
+	case CreditsOnly:
 		return batch.Error("ServiceClassCode", ErrBatchServiceClassCode, batch.Header.ServiceClassCode)
 	}
 
diff --git a/batchRCK.go b/batchRCK.go
index 337a056c..6df02895 100644
--- a/batchRCK.go
+++ b/batchRCK.go
@@ -51,7 +51,7 @@ func (batch *BatchRCK) Validate() error {
 
 	// RCK detail entries can only be a debit, ServiceClassCode must allow debits
 	switch batch.Header.ServiceClassCode {
-	case MixedDebitsAndCredits, CreditsOnly:
+	case CreditsOnly:
 		return batch.Error("ServiceClassCode", ErrBatchServiceClassCode, batch.Header.ServiceClassCode)
 	}
 
diff --git a/batchTRC.go b/batchTRC.go
index b898c4f4..2e709784 100644
--- a/batchTRC.go
+++ b/batchTRC.go
@@ -50,7 +50,7 @@ func (batch *BatchTRC) Validate() error {
 
 	// TRC detail entries can only be a debit, ServiceClassCode must allow debits
 	switch batch.Header.ServiceClassCode {
-	case MixedDebitsAndCredits, CreditsOnly:
+	case CreditsOnly:
 		return batch.Error("ServiceClassCode", ErrBatchServiceClassCode, batch.Header.ServiceClassCode)
 	}
 
diff --git a/batchTRX.go b/batchTRX.go
index 586858a0..d8014996 100644
--- a/batchTRX.go
+++ b/batchTRX.go
@@ -54,7 +54,7 @@ func (batch *BatchTRX) Validate() error {
 
 	// TRX detail entries can only be a debit, ServiceClassCode must allow debits
 	switch batch.Header.ServiceClassCode {
-	case MixedDebitsAndCredits, CreditsOnly:
+	case CreditsOnly:
 		return batch.Error("ServiceClassCode", ErrBatchServiceClassCode, batch.Header.ServiceClassCode)
 	}
 
diff --git a/batchXCK.go b/batchXCK.go
index 9ac79086..b0be396f 100644
--- a/batchXCK.go
+++ b/batchXCK.go
@@ -50,7 +50,7 @@ func (batch *BatchXCK) Validate() error {
 
 	// XCK detail entries can only be a debit, ServiceClassCode must allow debits
 	switch batch.Header.ServiceClassCode {
-	case MixedDebitsAndCredits, CreditsOnly:
+	case CreditsOnly:
 		return batch.Error("ServiceClassCode", ErrBatchServiceClassCode, batch.Header.ServiceClassCode)
 	}
 


Test patch:
diff --git a/batchARC_test.go b/batchARC_test.go
index 48ebce7e..b71c13c1 100644
--- a/batchARC_test.go
+++ b/batchARC_test.go
@@ -408,3 +408,19 @@ func TestBatchARCAddendum99Category(t *testing.T) {
 		t.Errorf("%T: %s", err, err)
 	}
 }
+
+// testBatchARCMixedCreditsAndDebits validates BatchARC create for valid MixedCreditsAndDebits
+func testBatchARCMixedCreditsAndDebitsBatchControlMixedDebitsAndCredits(t testing.TB) {
+	mockBatch := mockBatchARC()
+	mockBatch.Header.ServiceClassCode = MixedDebitsAndCredits
+	mockBatch.Batch.Control.ServiceClassCode = MixedDebitsAndCredits
+	err := mockBatch.Validate()
+	if err != nil {
+		t.Errorf("%T: %s", err, err)
+	}
+}
+
+// TestBatchARCMixedCreditsAndDebitsBatchControlMixedDebitsAndCredits tests validating BatchARC create for valid MixedCreditsAndDebits
+func TestBatchARCMixedCreditsAndDebitsBatchControlMixedDebitsAndCredits(t *testing.T) {
+	testBatchARCMixedCreditsAndDebitsBatchControlMixedDebitsAndCredits(t)
+}
diff --git a/batchBOC_test.go b/batchBOC_test.go
index 6c805fa1..a197672e 100644
--- a/batchBOC_test.go
+++ b/batchBOC_test.go
@@ -395,3 +395,19 @@ func TestBatchBOCAddendum99(t *testing.T) {
 		t.Errorf("%T: %s", err, err)
 	}
 }
+
+// testBatchBOCCreditsOnly validates BatchBOC create for Valid SCC MixedDebitsAndCredits with transCode Debit
+func testBatchBOCMixedDebitsAndCreditsWithCreditTransCode(t testing.TB) {
+	mockBatch := mockBatchBOC()
+	mockBatch.Header.ServiceClassCode = MixedDebitsAndCredits
+	mockBatch.Batch.Control.ServiceClassCode = MixedDebitsAndCredits
+	err := mockBatch.Validate()
+	if err != nil {
+		t.Errorf("%T: %s", err, err)
+	}
+}
+
+// TestBatchBOCCreditsOnly tests validating BatchBOC create for Valid SCC MixedDebitsAndCredits with transCode Debit
+func TestMixedDebitsAndCreditsWithCreditTransCode(t *testing.T) {
+	testBatchBOCMixedDebitsAndCreditsWithCreditTransCode(t)
+}
diff --git a/batchCIE_test.go b/batchCIE_test.go
index 5e2b414a..0a4f1d2a 100644
--- a/batchCIE_test.go
+++ b/batchCIE_test.go
@@ -437,3 +437,19 @@ func TestBatchCIEAddenda02(t *testing.T) {
 		t.Errorf("%T: %s", err, err)
 	}
 }
+
+// testBatchCIEServiceClassCodeEquality validates service class code MixedDebitsAndCredits
+func testBatchCIEMixedDebitsAndCreditsServiceClassCode(t testing.TB) {
+	mockBatch := mockBatchCIE()
+	mockBatch.GetControl().ServiceClassCode = MixedDebitsAndCredits
+	mockBatch.Header.ServiceClassCode = MixedDebitsAndCredits
+	err := mockBatch.Validate()
+	if err != nil {
+		t.Errorf("%T: %s", err, err)
+	}
+}
+
+// TestBatchCIEMixedDebitsAndCreditsServiceClassCode tests validating SCC MixedDebitsAndCredits
+func TestBatchCIEMixedDebitsAndCreditsServiceClassCode(t *testing.T) {
+	testBatchCIEMixedDebitsAndCreditsServiceClassCode(t)
+}
diff --git a/batchPOP_test.go b/batchPOP_test.go
index 066b8e0e..9cc2c75b 100644
--- a/batchPOP_test.go
+++ b/batchPOP_test.go
@@ -474,3 +474,18 @@ func TestBatchPOPAddendum99(t *testing.T) {
 		t.Errorf("%T: %s", err, err)
 	}
 }
+
+func testBatchPOPMixedDebitsAndCredits(t testing.TB) {
+	mockBatch := mockBatchPOP()
+	mockBatch.Header.ServiceClassCode = MixedDebitsAndCredits
+	mockBatch.Batch.Control.ServiceClassCode = MixedDebitsAndCredits
+	err := mockBatch.Validate()
+	if err != nil {
+		t.Errorf("%T: %s", err, err)
+	}
+}
+
+// TestBatchPOPMixedDebitsAndCredits tests validating BatchPOP create for MixedDebitsAndCredits with debit transaction code
+func TestBatchPOPMixedDebitsAndCredits(t *testing.T) {
+	testBatchPOPMixedDebitsAndCredits(t)
+}
diff --git a/batchRCK_test.go b/batchRCK_test.go
index 2af62570..1ec60587 100644
--- a/batchRCK_test.go
+++ b/batchRCK_test.go
@@ -444,3 +444,19 @@ func TestBatchRCKAddendum99(t *testing.T) {
 		t.Errorf("%T: %s", err, err)
 	}
 }
+
+// testBatchRCKServiceClassCodeEquality validates MixedDebitsAndCredits service class code
+func testBatchRCKMixedDebitsAndCreditsServiceClassCode(t testing.TB) {
+	mockBatch := mockBatchRCK()
+	mockBatch.GetControl().ServiceClassCode = MixedDebitsAndCredits
+	mockBatch.Header.ServiceClassCode = MixedDebitsAndCredits
+	err := mockBatch.Validate()
+	if err != nil {
+		t.Errorf("%T: %s", err, err)
+	}
+}
+
+// TestBatchRCKServiceClassCodeEquality tests validating MixedDebitsAndCredits service class code
+func TestBatchRCKMixedDebitsAndCreditsServiceClassCode(t *testing.T) {
+	testBatchRCKMixedDebitsAndCreditsServiceClassCode(t)
+}
diff --git a/batchTRC_test.go b/batchTRC_test.go
index a9235031..6e0284f0 100644
--- a/batchTRC_test.go
+++ b/batchTRC_test.go
@@ -425,3 +425,19 @@ func TestBatchTRCItemTypeIndicator(t *testing.T) {
 		t.Error("ItemTypeIndicator does not validate")
 	}
 }
+
+// testBatchTRCMixedDebitsAndCreditsServiceClassCodeEquality validates service class code
+func testBatchTRCMixedDebitsAndCreditsServiceClassCode(t testing.TB) {
+	mockBatch := mockBatchTRC()
+	mockBatch.GetControl().ServiceClassCode = MixedDebitsAndCredits
+	mockBatch.Header.ServiceClassCode = MixedDebitsAndCredits
+	err := mockBatch.Validate()
+	if err != nil {
+		t.Errorf("%T: %s", err, err)
+	}
+}
+
+// TestBatchTRCMixedDebitsAndCreditsServiceClassCodeEquality tests validating service class code
+func TestBatchTRCMixedDebitsAndCreditsServiceClassCode(t *testing.T) {
+	testBatchTRCMixedDebitsAndCreditsServiceClassCode(t)
+}
diff --git a/batchTRX_test.go b/batchTRX_test.go
index daad92c8..f5d2947c 100644
--- a/batchTRX_test.go
+++ b/batchTRX_test.go
@@ -600,3 +600,19 @@ func TestBatchTRXAddenda02(t *testing.T) {
 		t.Errorf("%T: %s", err, err)
 	}
 }
+
+// testBatchTRXMixedDebitsAndCreditsServiceClassCode validates MixedDebitsAndCredits service class code
+func testBatchTRXMixedDebitsAndCreditsServiceClassCode(t testing.TB) {
+	mockBatch := mockBatchTRX()
+	mockBatch.GetControl().ServiceClassCode = MixedDebitsAndCredits
+	mockBatch.Header.ServiceClassCode = MixedDebitsAndCredits
+	err := mockBatch.Validate()
+	if err != nil {
+		t.Errorf("%T: %s", err, err)
+	}
+}
+
+// TestBatchTRXMixedDebitsAndCreditsServiceClassCode tests validates MixedDebitsAndCredits service class code
+func TestBatchTRXMixedDebitsAndCreditsServiceClassCode(t *testing.T) {
+	testBatchTRXMixedDebitsAndCreditsServiceClassCode(t)
+}
diff --git a/batchXCK_test.go b/batchXCK_test.go
index 1fb20d58..b437d2db 100644
--- a/batchXCK_test.go
+++ b/batchXCK_test.go
@@ -423,3 +423,19 @@ func TestBatchXCKAmount(t *testing.T) {
 		t.Errorf("%T: %s", err, err)
 	}
 }
+
+// testBatchXCKMixedDebitsAndCreditsServiceClassCode validates MixedDebitsAndCredits service class code
+func testBatchXCKMixedDebitsAndCreditsServiceClassCode(t testing.TB) {
+	mockBatch := mockBatchXCK()
+	mockBatch.GetControl().ServiceClassCode = MixedDebitsAndCredits
+	mockBatch.Header.ServiceClassCode = MixedDebitsAndCredits
+	err := mockBatch.Validate()
+	if err != nil {
+		t.Errorf("%T: %s", err, err)
+	}
+}
+
+// TestBatchXCKMixedDebitsAndCreditsServiceClassCode tests validates MixedDebitsAndCredits service class code
+func TestBatchXCKMixedDebitsAndCreditsServiceClassCode(t *testing.T) {
+	testBatchXCKMixedDebitsAndCreditsServiceClassCode(t)
+}