Skip to content

Commit 271c3d8

Browse files
authored
Merge pull request #1745 from vkemthur-luna/fix-flatten-validation-propagation
fix: propagate file validation options to batches during flatten
2 parents 6398a52 + c0ccb84 commit 271c3d8

File tree

2 files changed

+154
-1
lines changed

2 files changed

+154
-1
lines changed

file_flattener.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ func Flatten(originalFile *File) (*File, error) {
9292
sort.Slice(allBatches, func(i int, j int) bool { return allBatches[i].GetBatchNumber() < allBatches[j].GetBatchNumber() })
9393

9494
for i := range allBatches {
95-
allBatches[i].AddToFile(newFile)
95+
if err := allBatches[i].AddToFile(newFile); err != nil {
96+
return nil, err
97+
}
9698
}
9799

98100
if err := newFile.Create(); err != nil {
@@ -208,6 +210,26 @@ func (m mergeableBatcher) AddToFile(file *File) error {
208210
return m.batcher.GetEntries()[i].TraceNumber < m.batcher.GetEntries()[j].TraceNumber
209211
})
210212

213+
// Inherit validation options from file if batch doesn't have them
214+
if file.GetValidation() != nil {
215+
// Use a local interface to access SetValidation
216+
type validatable interface {
217+
SetValidation(*ValidateOpts)
218+
}
219+
220+
if v, ok := m.batcher.(validatable); ok {
221+
v.SetValidation(file.GetValidation())
222+
223+
// Also set validation on all entries
224+
for _, entry := range m.batcher.GetEntries() {
225+
entry.SetValidation(file.GetValidation())
226+
}
227+
for _, entry := range m.batcher.GetADVEntries() {
228+
entry.SetValidation(file.GetValidation())
229+
}
230+
}
231+
}
232+
211233
err := m.batcher.Create()
212234
if err != nil {
213235
return askForBugReports(fmt.Errorf("mergeableBatcher - AddToFile: %v", err))
@@ -276,6 +298,16 @@ func (m mergeableIATBatch) AddToFile(file *File) error {
276298
return m.iatBatch.Entries[i].TraceNumber < m.iatBatch.Entries[j].TraceNumber
277299
})
278300

301+
// Inherit validation options from file
302+
if file.GetValidation() != nil {
303+
m.iatBatch.SetValidation(file.GetValidation())
304+
305+
// Also set validation on all entries
306+
for _, entry := range m.iatBatch.Entries {
307+
entry.SetValidation(file.GetValidation())
308+
}
309+
}
310+
279311
err := m.iatBatch.Create()
280312
if err != nil {
281313
return askForBugReports(fmt.Errorf("mergeableIATBatch - AddToFile: %v", err))

file_flattener_test.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,124 @@ func TestFlattenFile_ValidateOpts(t *testing.T) {
221221
require.NotNil(t, opts)
222222
require.True(t, opts.SkipAll)
223223
}
224+
225+
func TestFlattenFile_PropagatesValidationToBatches(t *testing.T) {
226+
// Create a file with multiple WEB batches that have entries with empty IndividualName
227+
// This tests that AllowEmptyIndividualName is propagated from file to batches during flatten
228+
229+
file := NewFile()
230+
file.SetHeader(mockFileHeader())
231+
232+
// Create two batches with the same header (so they'll be flattened together)
233+
// but with entries that have empty IndividualName
234+
for i := 0; i < 2; i++ {
235+
bh := NewBatchHeader()
236+
bh.ServiceClassCode = MixedDebitsAndCredits
237+
bh.CompanyName = "Test Company"
238+
bh.CompanyIdentification = "1234567890"
239+
bh.StandardEntryClassCode = WEB
240+
bh.CompanyEntryDescription = "Test"
241+
bh.ODFIIdentification = "12104288"
242+
243+
batch, err := NewBatch(bh)
244+
require.NoError(t, err)
245+
246+
// Set validation to allow empty names during batch creation
247+
batch.SetValidation(&ValidateOpts{
248+
AllowEmptyIndividualName: true,
249+
})
250+
251+
// Add entry with empty IndividualName (only spaces)
252+
entry := NewEntryDetail()
253+
entry.TransactionCode = CheckingCredit
254+
entry.RDFIIdentification = "12345678"
255+
entry.CheckDigit = "0"
256+
entry.DFIAccountNumber = "123456789"
257+
entry.Amount = 100000
258+
entry.IndividualName = " " // 22 spaces - empty name
259+
entry.TraceNumber = fmt.Sprintf("121042880000%03d", i+1)
260+
entry.IdentificationNumber = "location1234567"
261+
262+
batch.AddEntry(entry)
263+
require.NoError(t, batch.Create())
264+
265+
file.AddBatch(batch)
266+
}
267+
268+
require.NoError(t, file.Create())
269+
270+
// Now set validation on the file and flatten
271+
file.SetValidation(&ValidateOpts{
272+
AllowEmptyIndividualName: true,
273+
})
274+
275+
// Flatten should succeed because validation is propagated to batches
276+
flattenedFile, err := Flatten(file)
277+
require.NoError(t, err)
278+
require.NotNil(t, flattenedFile)
279+
280+
// Verify we have one batch (two were merged)
281+
require.Equal(t, 1, len(flattenedFile.Batches))
282+
283+
// Verify the batch has both entries
284+
require.Equal(t, 2, len(flattenedFile.Batches[0].GetEntries()))
285+
286+
// Verify entries still have empty names
287+
for _, entry := range flattenedFile.Batches[0].GetEntries() {
288+
require.Equal(t, " ", entry.IndividualName)
289+
}
290+
291+
// Verify file-level validation was preserved
292+
opts := flattenedFile.GetValidation()
293+
require.NotNil(t, opts)
294+
require.True(t, opts.AllowEmptyIndividualName)
295+
}
296+
297+
func TestFlattenFile_ValidationPropagationFailsWithoutOpts(t *testing.T) {
298+
// This test verifies that without AllowEmptyIndividualName,
299+
// flattening batches with empty names will fail
300+
301+
file := NewFile()
302+
file.SetHeader(mockFileHeader())
303+
304+
// Create batch with empty IndividualName
305+
bh := NewBatchHeader()
306+
bh.ServiceClassCode = MixedDebitsAndCredits
307+
bh.CompanyName = "Test Company"
308+
bh.CompanyIdentification = "1234567890"
309+
bh.StandardEntryClassCode = WEB
310+
bh.CompanyEntryDescription = "Test"
311+
bh.ODFIIdentification = "12104288"
312+
313+
batch, err := NewBatch(bh)
314+
require.NoError(t, err)
315+
316+
// Initially allow empty names to create the batch
317+
batch.SetValidation(&ValidateOpts{
318+
AllowEmptyIndividualName: true,
319+
})
320+
321+
entry := NewEntryDetail()
322+
entry.TransactionCode = CheckingCredit
323+
entry.RDFIIdentification = "12345678"
324+
entry.CheckDigit = "0"
325+
entry.DFIAccountNumber = "123456789"
326+
entry.Amount = 100000
327+
entry.IndividualName = " " // 22 spaces - empty name
328+
entry.TraceNumber = "121042880000001"
329+
entry.IdentificationNumber = "location1234567"
330+
331+
batch.AddEntry(entry)
332+
require.NoError(t, batch.Create())
333+
334+
file.AddBatch(batch)
335+
require.NoError(t, file.Create())
336+
337+
// Don't set validation on file (or set it without AllowEmptyIndividualName)
338+
file.SetValidation(&ValidateOpts{})
339+
340+
// Flatten should fail because validation is not allowing empty names
341+
_, err = Flatten(file)
342+
require.Error(t, err)
343+
require.Contains(t, err.Error(), "IndividualName")
344+
}

0 commit comments

Comments
 (0)