Skip to content
This repository was archived by the owner on Jul 28, 2025. It is now read-only.

Commit 999ef40

Browse files
committed
WIP
1 parent 741cbfe commit 999ef40

File tree

7 files changed

+365
-6
lines changed

7 files changed

+365
-6
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System.Text.RegularExpressions;
2+
using ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents.Models;
3+
4+
namespace ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents.Validation;
5+
6+
public partial class FileValidator : IFileValidator
7+
{
8+
private readonly HeaderFieldRegexValidator _headerExtractIdValidator = new(
9+
x => x.ExtractId, "Extract ID", ExtractIdRegex(),
10+
ErrorCodes.MissingExtractId, ErrorCodes.InvalidExtractId);
11+
12+
private readonly HeaderFieldRegexValidator _headerIdRecordCountValidator = new(
13+
x => x.RecordCount, "Record count", RecordCountRegex(),
14+
ErrorCodes.MissingRecordCount, ErrorCodes.InvalidRecordCount);
15+
16+
public IEnumerable<ValidationError> Validate(ParsedFile file)
17+
{
18+
if (file.FileHeader == null)
19+
{
20+
yield return new ValidationError
21+
{
22+
Code = ErrorCodes.MissingHeader,
23+
Error = "Header is missing",
24+
Scope = ValidationErrorScope.File
25+
};
26+
}
27+
else
28+
{
29+
foreach (var error in _headerExtractIdValidator.Validate(file))
30+
{
31+
yield return error;
32+
}
33+
34+
foreach (var error in _headerIdRecordCountValidator.Validate(file))
35+
{
36+
yield return error;
37+
}
38+
}
39+
40+
if (file.FileTrailer == null)
41+
{
42+
yield return new ValidationError
43+
{
44+
Code = ErrorCodes.MissingTrailer,
45+
Error = "Trailer is missing",
46+
Scope = ValidationErrorScope.File
47+
};
48+
}
49+
else if (file.FileHeader !=null)
50+
{
51+
if (file.FileHeader.ExtractId != file.FileTrailer.ExtractId)
52+
{
53+
yield return new ValidationError
54+
{
55+
Field = "Extract ID",
56+
Code = ErrorCodes.InconsistentExtractId,
57+
Error = "Extract ID does not match value in header",
58+
Scope = ValidationErrorScope.Trailer
59+
};
60+
}
61+
62+
if (file.FileHeader.RecordCount != file.FileTrailer.RecordCount)
63+
{
64+
yield return new ValidationError
65+
{
66+
Field = "Record count",
67+
Code = ErrorCodes.InconsistentRecordCount,
68+
Error = "Record count does not match value in header",
69+
Scope = ValidationErrorScope.Trailer
70+
};
71+
}
72+
73+
if (file.DataRecords.Count != int.Parse(file.FileHeader.RecordCount!))
74+
{
75+
yield return new ValidationError
76+
{
77+
Code = ErrorCodes.UnexpectedRecordCount,
78+
Error = "Record count does not match value in header and footer",
79+
Scope = ValidationErrorScope.File
80+
};
81+
}
82+
}
83+
}
84+
85+
[GeneratedRegex(@"^\d{8}$")]
86+
private static partial Regex ExtractIdRegex();
87+
88+
[GeneratedRegex(@"^(?!000000)\d{6}$")]
89+
private static partial Regex RecordCountRegex();
90+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System.Linq.Expressions;
2+
using System.Text.RegularExpressions;
3+
using ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents.Models;
4+
5+
namespace ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents.Validation;
6+
7+
public class HeaderFieldRegexValidator(
8+
Expression<Func<FileHeaderRecord, string?>> fieldSelector,
9+
string fieldName,
10+
Regex pattern,
11+
string errorCodeMissing,
12+
string errorCodeInvalidFormat)
13+
: IFileValidator
14+
{
15+
public IEnumerable<ValidationError> Validate(ParsedFile file)
16+
{
17+
var header = file.FileHeader!;
18+
var value = fieldSelector.Compile().Invoke(header);
19+
20+
if (value == null)
21+
{
22+
yield return new ValidationError
23+
{
24+
Scope = ValidationErrorScope.Header,
25+
Field = fieldName,
26+
Error = $"{fieldName} is missing",
27+
Code = errorCodeMissing,
28+
};
29+
yield break;
30+
}
31+
32+
if (!pattern.IsMatch(value))
33+
{
34+
yield return new ValidationError
35+
{
36+
Scope = ValidationErrorScope.Header,
37+
Field = fieldName,
38+
Error = $"{fieldName} is in an invalid format",
39+
Code = errorCodeInvalidFormat,
40+
};
41+
}
42+
}
43+
}

src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/ValidatorRegistry.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Runtime.InteropServices.JavaScript;
21
using System.Text.RegularExpressions;
32

43
namespace ServiceLayer.Mesh.FileTypes.NbssAppointmentEvents.Validation;
@@ -69,7 +68,7 @@ public static IEnumerable<IRecordValidator> GetAllRecordValidators()
6968

7069
public static IEnumerable<IFileValidator> GetAllFileValidators()
7170
{
72-
return [];
71+
return [new FileValidator()];
7372
}
7473

7574
[GeneratedRegex(@"^[BCU]$", RegexOptions.Compiled)]

src/ServiceLayer.Mesh/ValidationError.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ public class ValidationError
44
{
55
public int? RowNumber { get; set; }
66

7-
public required string Field { get; set; }
7+
public string? Field { get; set; }
88

99
public required string Code { get; set; }
1010

tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/TestDataBuilder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public static ParsedFile BuildValidParsedFile(int numberOfRecords = 3)
1212
ExtractId = "00000107",
1313
TransferStartDate = "20250519",
1414
TransferStartTime = "153806",
15-
RecordCount = numberOfRecords.ToString()
15+
RecordCount = numberOfRecords.ToString("D6")
1616
};
1717

1818
var trailer = new FileTrailerRecord
@@ -21,7 +21,7 @@ public static ParsedFile BuildValidParsedFile(int numberOfRecords = 3)
2121
ExtractId = "00000107",
2222
TransferEndDate = "20250519",
2323
TransferEndTime = "153957",
24-
RecordCount = numberOfRecords.ToString()
24+
RecordCount = numberOfRecords.ToString("D6")
2525
};
2626

2727
var dataRecords = Enumerable.Range(1, numberOfRecords)

0 commit comments

Comments
 (0)