Skip to content

Commit

Permalink
cashLetterControl: settlement date should not be mandatory (#319)
Browse files Browse the repository at this point in the history
  • Loading branch information
atonks2 authored Aug 15, 2023
1 parent 0435ccd commit c0c5c78
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 23 deletions.
2 changes: 1 addition & 1 deletion cashLetter.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (cl *CashLetter) Validate() error {
}
}

if err := cl.CashLetterControl.Validate(cl.CashLetterHeader.CollectionTypeIndicator); err != nil {
if err := cl.CashLetterControl.Validate(); err != nil {
return err
}

Expand Down
19 changes: 11 additions & 8 deletions cashLetterControl.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ func (clc *CashLetterControl) String() string {

// Validate performs imagecashletter format rule checks on the record and returns an error if not Validated
// The first error encountered is returned and stops the parsing.
func (clc *CashLetterControl) Validate(collectionTypeIndicator string) error {
if err := clc.fieldInclusion(collectionTypeIndicator); err != nil {
func (clc *CashLetterControl) Validate() error {
if err := clc.fieldInclusion(); err != nil {
return err
}
if clc.recordType != "90" {
Expand All @@ -149,7 +149,7 @@ func (clc *CashLetterControl) Validate(collectionTypeIndicator string) error {

// fieldInclusion validate mandatory fields are not default values. If fields are
// invalid the Electronic Exchange will be returned.
func (clc *CashLetterControl) fieldInclusion(collectionTypeIndicator string) error {
func (clc *CashLetterControl) fieldInclusion() error {
if clc.recordType == "" {
return &FieldError{FieldName: "recordType",
Value: clc.recordType,
Expand All @@ -165,12 +165,15 @@ func (clc *CashLetterControl) fieldInclusion(collectionTypeIndicator string) err
Value: clc.CashLetterTotalAmountField(),
Msg: msgFieldInclusion + ", did you use CashLetterControl()?"}
}
// If the type of the cash letter control is `Return`, we do not require to have this field present.
if clc.SettlementDate.IsZero() && !isReturnCollectionType(collectionTypeIndicator) {
return &FieldError{FieldName: "SettlementDate",
Value: clc.SettlementDate.String(),
Msg: msgFieldInclusion + ", did you use CashLetterControl()?"}

// optional field - if present, year must be between 1993 and 9999
if date := clc.SettlementDate; !date.IsZero() {
if date.Year() < 1993 || date.Year() > 9999 {
return &FieldError{FieldName: "SettlementDate",
Value: clc.SettlementDateField(), Msg: msgInvalidDate + ": year must be between 1993 and 9999"}
}
}

return nil
}

Expand Down
44 changes: 33 additions & 11 deletions cashLetterControl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func mockCashLetterControl() *CashLetterControl {
// TestMockCashLetterControl creates a CashLetterControl
func TestMockCashLetterControl(t *testing.T) {
clc := mockCashLetterControl()
require.NoError(t, clc.Validate("01"))
require.NoError(t, clc.Validate())
require.Equal(t, "90", clc.recordType)
require.Equal(t, 1, clc.CashLetterBundleCount)
require.Equal(t, 7, clc.CashLetterItemsCount)
Expand All @@ -45,7 +45,7 @@ func TestParseCashLetterControl(t *testing.T) {
r.line = line
clh := mockCashLetterHeader()
r.addCurrentCashLetter(NewCashLetter(clh))
require.NoError(t, r.parseCashLetterControl("03"))
require.NoError(t, r.parseCashLetterControl())
record := r.currentCashLetter.CashLetterControl

require.Equal(t, "90", record.recordType)
Expand All @@ -66,7 +66,7 @@ func testCLCString(t testing.TB) {
r.line = line
clh := mockCashLetterHeader()
r.addCurrentCashLetter(NewCashLetter(clh))
require.NoError(t, r.parseCashLetterControl("01"))
require.NoError(t, r.parseCashLetterControl())
record := r.currentCashLetter.CashLetterControl
require.Equal(t, line, record.String())
}
Expand All @@ -88,7 +88,7 @@ func BenchmarkCLCString(b *testing.B) {
func TestCLCRecordType(t *testing.T) {
clc := mockCashLetterControl()
clc.recordType = "00"
err := clc.Validate("01")
err := clc.Validate()
var fieldErr *FieldError
require.ErrorAs(t, err, &fieldErr)
require.Equal(t, "recordType", fieldErr.FieldName)
Expand All @@ -98,7 +98,7 @@ func TestCLCRecordType(t *testing.T) {
func TestECEInstitutionName(t *testing.T) {
clc := mockCashLetterControl()
clc.ECEInstitutionName = "®©"
err := clc.Validate("01")
err := clc.Validate()
var fieldErr *FieldError
require.ErrorAs(t, err, &fieldErr)
require.Equal(t, "ECEInstitutionName", fieldErr.FieldName)
Expand All @@ -108,7 +108,7 @@ func TestECEInstitutionName(t *testing.T) {
func TestCLCCreditTotalIndicator(t *testing.T) {
clc := mockCashLetterControl()
clc.CreditTotalIndicator = 9
err := clc.Validate("01")
err := clc.Validate()
var fieldErr *FieldError
require.ErrorAs(t, err, &fieldErr)
require.Equal(t, "CreditTotalIndicator", fieldErr.FieldName)
Expand All @@ -118,7 +118,7 @@ func TestCLCCreditTotalIndicator(t *testing.T) {
func TestCLCFieldInclusionRecordType(t *testing.T) {
clc := mockCashLetterControl()
clc.recordType = ""
err := clc.Validate("01")
err := clc.Validate()
var fieldErr *FieldError
require.ErrorAs(t, err, &fieldErr)
require.Equal(t, "recordType", fieldErr.FieldName)
Expand All @@ -128,7 +128,7 @@ func TestCLCFieldInclusionRecordType(t *testing.T) {
func TestFieldInclusionCashLetterItemsCount(t *testing.T) {
clc := mockCashLetterControl()
clc.CashLetterItemsCount = 0
err := clc.Validate("01")
err := clc.Validate()
var fieldErr *FieldError
require.ErrorAs(t, err, &fieldErr)
require.Equal(t, "CashLetterItemsCount", fieldErr.FieldName)
Expand All @@ -138,7 +138,7 @@ func TestFieldInclusionCashLetterItemsCount(t *testing.T) {
func TestFieldInclusionCashLetterTotalAmount(t *testing.T) {
clc := mockCashLetterControl()
clc.CashLetterTotalAmount = 0
err := clc.Validate("01")
err := clc.Validate()
var fieldErr *FieldError
require.ErrorAs(t, err, &fieldErr)
require.Equal(t, "CashLetterTotalAmount", fieldErr.FieldName)
Expand All @@ -147,8 +147,9 @@ func TestFieldInclusionCashLetterTotalAmount(t *testing.T) {
// TestFieldInclusionSettlementDate validates FieldInclusion
func TestFieldInclusionRecordTypeSettlementDate(t *testing.T) {
clc := mockCashLetterControl()
clc.SettlementDate = time.Time{}
err := clc.Validate("01")
// if present (non-zero), SettlementDate.Year() must be between 1993 and 9999
clc.SettlementDate = time.Date(40010, time.November, 9, 0, 0, 0, 0, time.UTC)
err := clc.Validate()
var fieldErr *FieldError
require.ErrorAs(t, err, &fieldErr)
require.Equal(t, "SettlementDate", fieldErr.FieldName)
Expand All @@ -162,3 +163,24 @@ func TestCashLetterControlRuneCountInString(t *testing.T) {

require.Equal(t, 0, clc.CashLetterBundleCount)
}

func TestCashLetterControl_isReturnCollectionType(t *testing.T) {
tests := []struct {
collectionType string
expected bool
}{
{"03", true},
{"04", true},
{"05", true},
{"06", true},
{"07", false},
{"01", false},
{"", false},
}

for _, tt := range tests {
t.Run(tt.collectionType, func(t *testing.T) {
require.Equal(t, tt.expected, isReturnCollectionType(tt.collectionType))
})
}
}
6 changes: 3 additions & 3 deletions reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ func (r *Reader) parseLine() error { //nolint:gocyclo
if header == nil {
return errors.New("missing CashLetterHeader")
}
if err := r.parseCashLetterControl(header.CollectionTypeIndicator); err != nil {
if err := r.parseCashLetterControl(); err != nil {
return err
}
if err := r.currentCashLetter.Validate(); err != nil {
Expand Down Expand Up @@ -707,15 +707,15 @@ func (r *Reader) parseRoutingNumberSummary() error {
}

// parseCashLetterControl takes the input record string and parses the CashLetterControl values
func (r *Reader) parseCashLetterControl(collectionTypeIndicator string) error {
func (r *Reader) parseCashLetterControl() error {
r.recordName = "CashLetterControl"
if r.currentCashLetter.CashLetterHeader == nil {
// CashLetterControl without a current CashLetter
return r.error(&FileError{Msg: msgFileCashLetterControl})
}
r.currentCashLetter.GetControl().Parse(r.decodeLine(r.line))
// Ensure valid CashLetterControl
if err := r.currentCashLetter.GetControl().Validate(collectionTypeIndicator); err != nil {
if err := r.currentCashLetter.GetControl().Validate(); err != nil {
return r.error(err)
}
return nil
Expand Down

0 comments on commit c0c5c78

Please sign in to comment.