diff --git a/src/main/java/de/gecheckt/asv/validation/structure/DefaultStructureValidator.java b/src/main/java/de/gecheckt/asv/validation/structure/DefaultStructureValidator.java index 5f15360..7863b94 100644 --- a/src/main/java/de/gecheckt/asv/validation/structure/DefaultStructureValidator.java +++ b/src/main/java/de/gecheckt/asv/validation/structure/DefaultStructureValidator.java @@ -26,6 +26,7 @@ import de.gecheckt.asv.validation.model.ValidationSeverity; * 8. Die im UNT angegebene Segmentanzahl muss der tatsächlichen Anzahl der Segmente entsprechen * 9. Eine Nachricht muss mindestens ein UNH-Segment enthalten * 10. Eine Nachricht muss mindestens ein UNT-Segment enthalten + * 11. UNH muss vor UNT stehen */ public class DefaultStructureValidator implements StructureValidator { @@ -111,6 +112,12 @@ public class DefaultStructureValidator implements StructureValidator { if (message.getFirstSegment("UNT").isPresent()) { validateUntSegmentCount(message, errors); } + + // Regel 11: UNH muss vor UNT stehen + // Nur prüfen, wenn beide Segmente vorhanden sind + if (message.getFirstSegment("UNH").isPresent() && message.getFirstSegment("UNT").isPresent()) { + validateUnhBeforeUnt(message, errors); + } } } @@ -207,6 +214,38 @@ public class DefaultStructureValidator implements StructureValidator { } } + /** + * Validiert, dass UNH vor UNT steht. + * + * @param message die zu validierende Nachricht + * @param errors die Liste zum Hinzufügen von Validierungsfehlern + */ + private void validateUnhBeforeUnt(Message message, List errors) { + var unhSegment = message.getFirstSegment("UNH"); + var untSegment = message.getFirstSegment("UNT"); + + // Prüft, ob beide Segmente vorhanden sind, bevor eine Validierung erfolgt + if (unhSegment.isPresent() && untSegment.isPresent()) { + int unhPosition = unhSegment.get().segmentPosition(); + int untPosition = untSegment.get().segmentPosition(); + + // UNH muss vor UNT stehen + if (unhPosition > untPosition) { + errors.add(createError( + "STRUCTURE_011", + "UNH muss vor UNT stehen", + ValidationSeverity.ERROR, + "UNH/UNT", + message.messagePosition(), + "", + 0, + "UNH at position " + unhPosition + ", UNT at position " + untPosition, + "UNH muss vor UNT stehen" + )); + } + } + } + /** * Validiert, dass die Referenznummern in UNH und UNT übereinstimmen. * diff --git a/src/test/java/de/gecheckt/asv/validation/structure/DefaultStructureValidatorTest.java b/src/test/java/de/gecheckt/asv/validation/structure/DefaultStructureValidatorTest.java index 1944438..9f5780f 100644 --- a/src/test/java/de/gecheckt/asv/validation/structure/DefaultStructureValidatorTest.java +++ b/src/test/java/de/gecheckt/asv/validation/structure/DefaultStructureValidatorTest.java @@ -438,4 +438,87 @@ class DefaultStructureValidatorTest { assertFalse(result.getErrors().stream() .anyMatch(error -> "STRUCTURE_008".equals(error.errorCode()))); } + + @Test + void validate_shouldReportErrorWhenUnhComesAfterUnt() throws IOException, InputFileParseException { + // Given + SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer(); + DefaultInputFileParser parser = new DefaultInputFileParser(tokenizer); + String fileName = "unt-before-unh-invalid.asv"; + Path filePath = Path.of("src/test/resources/unt-before-unh-invalid.asv"); + String fileContent = Files.readString(filePath); + + // When + InputFile inputFile = parser.parse(fileName, fileContent); + ValidationResult result = validator.validate(inputFile); + + // Then + assertTrue(result.hasErrors()); + assertEquals(1, result.getErrors().size()); + + ValidationError error = result.getErrors().get(0); + assertEquals("STRUCTURE_011", error.errorCode()); + assertEquals("UNH muss vor UNT stehen", error.description()); + assertEquals("UNH/UNT", error.segmentName()); + assertEquals(1, error.segmentPosition()); + assertEquals("UNH at position 9, UNT at position 1", error.actualValue()); + assertEquals("UNH muss vor UNT stehen", error.expectedRule()); + } + + @Test + void validate_shouldNotReportErrorWhenUnhComesBeforeUnt() throws IOException, InputFileParseException { + // Given + SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer(); + DefaultInputFileParser parser = new DefaultInputFileParser(tokenizer); + String fileName = "unh-before-unt-valid.asv"; + Path filePath = Path.of("src/test/resources/unh-before-unt-valid.asv"); + String fileContent = Files.readString(filePath); + + // When + InputFile inputFile = parser.parse(fileName, fileContent); + ValidationResult result = validator.validate(inputFile); + + // Then + // Should not have STRUCTURE_011 error for UNH/UNT order + assertFalse(result.getErrors().stream() + .anyMatch(error -> "STRUCTURE_011".equals(error.errorCode()))); + } + + @Test + void validate_shouldNotReportErrorWhenUnhIsMissing() throws IOException, InputFileParseException { + // Given + SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer(); + DefaultInputFileParser parser = new DefaultInputFileParser(tokenizer); + String fileName = "no-unh.asv"; + Path filePath = Path.of("src/test/resources/no-unh.asv"); + String fileContent = Files.readString(filePath); + + // When + InputFile inputFile = parser.parse(fileName, fileContent); + ValidationResult result = validator.validate(inputFile); + + // Then + // Should not have STRUCTURE_011 error for UNH/UNT order when UNH is missing + assertFalse(result.getErrors().stream() + .anyMatch(error -> "STRUCTURE_011".equals(error.errorCode()))); + } + + @Test + void validate_shouldNotReportErrorWhenUntIsMissing() throws IOException, InputFileParseException { + // Given + SegmentLineTokenizer tokenizer = new DefaultSegmentLineTokenizer(); + DefaultInputFileParser parser = new DefaultInputFileParser(tokenizer); + String fileName = "no-unt.asv"; + Path filePath = Path.of("src/test/resources/no-unt.asv"); + String fileContent = Files.readString(filePath); + + // When + InputFile inputFile = parser.parse(fileName, fileContent); + ValidationResult result = validator.validate(inputFile); + + // Then + // Should not have STRUCTURE_011 error for UNH/UNT order when UNT is missing + assertFalse(result.getErrors().stream() + .anyMatch(error -> "STRUCTURE_011".equals(error.errorCode()))); + } } \ No newline at end of file diff --git a/src/test/resources/unh-before-unt-valid.asv b/src/test/resources/unh-before-unt-valid.asv new file mode 100644 index 0000000..c5da9ec --- /dev/null +++ b/src/test/resources/unh-before-unt-valid.asv @@ -0,0 +1,9 @@ +UNH+1+ORDERS:D:03B:UN:EAN008' +BGM+220+100001' +DTM+137:20260325:102' +NAD+BY+5000000000000:16++Customer Name' +LIN+1++Product123:SA' +QTY+21:10:PCE' +UNS+S' +CNT+2:1' +UNT+8+1' \ No newline at end of file diff --git a/src/test/resources/unt-before-unh-invalid.asv b/src/test/resources/unt-before-unh-invalid.asv new file mode 100644 index 0000000..e4402c8 --- /dev/null +++ b/src/test/resources/unt-before-unh-invalid.asv @@ -0,0 +1,9 @@ +UNT+9+1' +BGM+220+100001' +DTM+137:20260325:102' +NAD+BY+5000000000000:16++Customer Name' +LIN+1++Product123:SA' +QTY+21:10:PCE' +UNS+S' +CNT+2:1' +UNH+1+ORDERS:D:03B:UN:EAN008' \ No newline at end of file