diff --git a/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/MaxLengthValidator.cs b/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/MaxLengthValidator.cs index b4ae58f..224c937 100644 --- a/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/MaxLengthValidator.cs +++ b/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/MaxLengthValidator.cs @@ -20,6 +20,7 @@ public IEnumerable Validate(FileDataRecord fileDataRecord) yield return new ValidationError { + Scope = ValidationErrorScope.Record, RowNumber = fileDataRecord.RowNumber, Field = fieldName, Error = error, @@ -34,6 +35,7 @@ public IEnumerable Validate(FileDataRecord fileDataRecord) yield return new ValidationError { + Scope = ValidationErrorScope.Record, RowNumber = fileDataRecord.RowNumber, Field = fieldName, Error = error, diff --git a/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/NhsNumValidator.cs b/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/NhsNumValidator.cs index 0899944..386acad 100644 --- a/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/NhsNumValidator.cs +++ b/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/NhsNumValidator.cs @@ -11,6 +11,7 @@ protected override IEnumerable RunAdditionalChecks(int rowNumbe { yield return new ValidationError { + Scope = ValidationErrorScope.Record, RowNumber = rowNumber, Field = FieldName, Error = "NHS Num has invalid check digit", diff --git a/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/RegexValidator.cs b/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/RegexValidator.cs index 4cb6779..4fe774a 100644 --- a/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/RegexValidator.cs +++ b/src/ServiceLayer.Mesh/FileTypes/NbssAppointmentEvents/Validation/RegexValidator.cs @@ -20,6 +20,7 @@ public IEnumerable Validate(FileDataRecord fileDataRecord) { yield return new ValidationError { + Scope = ValidationErrorScope.Record, RowNumber = fileDataRecord.RowNumber, Field = FieldName, Error = $"{FieldName} is missing", @@ -32,6 +33,7 @@ public IEnumerable Validate(FileDataRecord fileDataRecord) { yield return new ValidationError { + Scope = ValidationErrorScope.Record, RowNumber = fileDataRecord.RowNumber, Field = FieldName, Error = $"{FieldName} is in an invalid format", diff --git a/src/ServiceLayer.Mesh/ValidationError.cs b/src/ServiceLayer.Mesh/ValidationError.cs index f5ea27e..2f6cd72 100644 --- a/src/ServiceLayer.Mesh/ValidationError.cs +++ b/src/ServiceLayer.Mesh/ValidationError.cs @@ -9,4 +9,6 @@ public class ValidationError public required string Code { get; set; } public required string Error { get; set; } + + public required ValidationErrorScope Scope { get; set; } } diff --git a/src/ServiceLayer.Mesh/ValidationErrorScope.cs b/src/ServiceLayer.Mesh/ValidationErrorScope.cs new file mode 100644 index 0000000..bcd1a56 --- /dev/null +++ b/src/ServiceLayer.Mesh/ValidationErrorScope.cs @@ -0,0 +1,9 @@ +namespace ServiceLayer.Mesh; + +public enum ValidationErrorScope +{ + File, + Record, + Header, + Trailer +} diff --git a/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/MaxLengthValidatorTests.cs b/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/MaxLengthValidatorTests.cs index ad95c38..7e9a98e 100644 --- a/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/MaxLengthValidatorTests.cs +++ b/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/MaxLengthValidatorTests.cs @@ -27,7 +27,7 @@ public void Validate_NullValue_ShouldReturnMissingError(bool allowEmpty, string var errors = validator.Validate(record).ToList(); // Assert - errors.ShouldContainValidationError(FieldName, expectedError, MissingCode, 1); + errors.ShouldContainValidationError(FieldName, expectedError, MissingCode, ValidationErrorScope.Record, 1); } [Fact] @@ -46,7 +46,7 @@ public void Validate_EmptyValueDisallowed_ShouldReturnMissingError() var errors = validator.Validate(record).ToList(); // Assert - errors.ShouldContainValidationError(FieldName, "TestField is missing or empty", MissingCode, 2); + errors.ShouldContainValidationError(FieldName, "TestField is missing or empty", MissingCode, ValidationErrorScope.Record,2); } [Fact] @@ -86,7 +86,7 @@ public void Validate_ValueExceedingMaxLength_ShouldReturnTooLongError(int maxLen var errors = validator.Validate(record).ToList(); // Assert - errors.ShouldContainValidationError(FieldName, $"TestField exceeds maximum length of {maxLength}", TooLongCode, 4); + errors.ShouldContainValidationError(FieldName, $"TestField exceeds maximum length of {maxLength}", TooLongCode, ValidationErrorScope.Record,4); } [Theory] diff --git a/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/RegexValidatorTests.cs b/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/RegexValidatorTests.cs index d7c81b8..0126379 100644 --- a/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/RegexValidatorTests.cs +++ b/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/RegexValidatorTests.cs @@ -27,7 +27,7 @@ public void Validate_NullValue_ShouldReturnMissingError() var errors = validator.Validate(record).ToList(); // Assert - errors.ShouldContainValidationError(FieldName, $"{FieldName} is missing", MissingCode, 1); + errors.ShouldContainValidationError(FieldName, $"{FieldName} is missing", MissingCode, ValidationErrorScope.Record,1); } [Theory] @@ -48,7 +48,7 @@ public void Validate_ValueNotMatchingPattern_ShouldReturnInvalidFormatError(stri var errors = validator.Validate(record).ToList(); // Assert - errors.ShouldContainValidationError(FieldName, $"{FieldName} is in an invalid format", InvalidFormatCode, 2); + errors.ShouldContainValidationError(FieldName, $"{FieldName} is in an invalid format", InvalidFormatCode,ValidationErrorScope.Record, 2); } [Theory] diff --git a/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/ValidationErrorAssertions.cs b/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/ValidationErrorAssertions.cs index 1f60bc0..3d125a7 100644 --- a/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/ValidationErrorAssertions.cs +++ b/tests/ServiceLayer.Mesh.Tests/FileTypes/NbssAppointmentEvents/Validation/ValidationErrorAssertions.cs @@ -7,6 +7,7 @@ public static void ShouldContainValidationError( string expectedField, string expectedError, string expectedCode, + ValidationErrorScope expectedScope = ValidationErrorScope.Record, int? expectedRowNumber = null) { var error = errors.FirstOrDefault(e => @@ -16,7 +17,7 @@ public static void ShouldContainValidationError( (expectedRowNumber == null || e.RowNumber == expectedRowNumber) ); - Assert.True(error != null, $"Expected validation error with Field: '{expectedField}', Error: '{expectedError}', Code: '{expectedCode}'{(expectedRowNumber != null ? $", RowNumber: {expectedRowNumber}" : "")}, but none was found."); + Assert.True(error != null, $"Expected validation error with Scope: '{expectedScope}', Field: '{expectedField}', Error: '{expectedError}', Code: '{expectedCode}'{(expectedRowNumber != null ? $", RowNumber: {expectedRowNumber}" : "")}, but none was found."); } } diff --git a/tests/ServiceLayer.Mesh.Tests/Functions/FileTransformFunctionTests.cs b/tests/ServiceLayer.Mesh.Tests/Functions/FileTransformFunctionTests.cs index d90b925..75966e5 100644 --- a/tests/ServiceLayer.Mesh.Tests/Functions/FileTransformFunctionTests.cs +++ b/tests/ServiceLayer.Mesh.Tests/Functions/FileTransformFunctionTests.cs @@ -139,8 +139,8 @@ public async Task Run_FileHasValidationErrors_ErrorLoggedAndStatusAndValidationE var validationErrors = new List { - new() { Code = "NBSSAPPT001", Error = "error message", Field = "field", RowNumber = 1 }, - new() { Code = "NBSSAPPT002", Error = "error message 2", Field = "field 2" } + new() { Scope = ValidationErrorScope.Record, Code = "NBSSAPPT001", Error = "error message", Field = "field", RowNumber = 1 }, + new() { Scope = ValidationErrorScope.Header, Code = "NBSSAPPT002", Error = "error message 2", Field = "field 2" } }; _fileTransformerMock.Setup(c => c.TransformFileAsync(expectedStream, file))