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 e5dd77f..a5b7daa 100644 --- a/src/main/java/de/gecheckt/asv/validation/structure/DefaultStructureValidator.java +++ b/src/main/java/de/gecheckt/asv/validation/structure/DefaultStructureValidator.java @@ -150,6 +150,9 @@ public class DefaultStructureValidator implements StructureValidator { // Neue Regel: Für ASVFEH-Nachrichten muss mindestens ein FHL-Segment vorhanden sein validateAsvfehRequiredFhlSegment(message, errors); + + // Neue Regel: Für ASVFEH-Nachrichten darf FHL höchstens 99-mal vorkommen + validateAsvfehFhlCardinality(message, errors); } } } @@ -843,6 +846,44 @@ public class DefaultStructureValidator implements StructureValidator { } } + /** + * Validiert, dass für ASVFEH-Nachrichten das FHL-Segment höchstens 99-mal vorkommt. + * Diese Regel greift nur für ASVFEH-Nachrichten. Für ASVREC wird keine Prüfung durchgeführt. + * Wenn kein FHL vorhanden ist, wird hier kein Fehler erzeugt (die Präsenzregel STRUCTURE_025 deckt das ab). + * + * @param message die zu validierende Nachricht + * @param errors die Liste zum Hinzufügen von Validierungsfehlern + */ + private void validateAsvfehFhlCardinality(Message message, List errors) { + var unhSegment = message.getFirstSegment("UNH"); + if (unhSegment.isEmpty()) { + return; + } + String messageType = extractMessageType(unhSegment.get()); + // Nur für ASVFEH-Nachrichten prüfen + if (!"ASVFEH".equals(messageType)) { + return; + } + + // Anzahl der FHL-Segmente zählen + int fhlCount = message.getSegments("FHL").size(); + + // Nur bei mehr als 99 Vorkommen einen Fehler erzeugen + if (fhlCount > 99) { + errors.add(createError( + "STRUCTURE_027", + "ASVFEH-Nachricht darf FHL höchstens 99-mal enthalten", + ValidationSeverity.ERROR, + "FHL", + message.messagePosition(), + "", + 0, + String.valueOf(fhlCount), + "FHL darf maximal 99-mal vorkommen" + )); + } + } + /** * Extrahiert den Nachrichtentyp aus dem UNH-Segment. * diff --git a/src/test/java/de/gecheckt/asv/validation/structure/DefaultStructureValidatorAsvfehFhlSegmentTest.java b/src/test/java/de/gecheckt/asv/validation/structure/DefaultStructureValidatorAsvfehFhlSegmentTest.java index 247e042..874c30d 100644 --- a/src/test/java/de/gecheckt/asv/validation/structure/DefaultStructureValidatorAsvfehFhlSegmentTest.java +++ b/src/test/java/de/gecheckt/asv/validation/structure/DefaultStructureValidatorAsvfehFhlSegmentTest.java @@ -2,6 +2,7 @@ package de.gecheckt.asv.validation.structure; import static org.junit.jupiter.api.Assertions.*; +import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.BeforeEach; @@ -111,4 +112,91 @@ class DefaultStructureValidatorAsvfehFhlSegmentTest { .anyMatch(error -> "STRUCTURE_025".equals(error.errorCode())), "STRUCTURE_025 Fehler sollte nicht auftreten für ASVREC"); } + + @Test + void validate_shouldNotReportErrorForAsvfehWithOneFhl() { + // Given: ASVFEH mit genau 1 FHL + Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVFEH:D:03B:UN:EAN008"))); + Segment fhl = new Segment("FHL", 2, List.of(new Field(1, "1"))); + Segment unt = new Segment("UNT", 3, List.of(new Field(1, "3"), new Field(2, "12345"))); + Message message = new Message(1, List.of(unh, fhl, unt)); + InputFile inputFile = new InputFile("test.txt", List.of(message)); + + // When + ValidationResult result = validator.validate(inputFile); + + // Then: Kein Fehler STRUCTURE_027 + assertFalse(result.getErrors().stream() + .anyMatch(error -> "STRUCTURE_027".equals(error.errorCode())), + "STRUCTURE_027 sollte nicht auftreten bei 1 FHL"); + } + + @Test + void validate_shouldNotReportErrorForAsvfehWith99Fhl() { + // Given: ASVFEH mit genau 99 FHL + List segments = new ArrayList<>(); + segments.add(new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVFEH:D:03B:UN:EAN008")))); + for (int i = 0; i < 99; i++) { + segments.add(new Segment("FHL", i + 2, List.of(new Field(1, String.valueOf(i + 1))))); + } + segments.add(new Segment("UNT", 101, List.of(new Field(1, "101"), new Field(2, "12345")))); + Message message = new Message(1, segments); + InputFile inputFile = new InputFile("test.txt", List.of(message)); + + // When + ValidationResult result = validator.validate(inputFile); + + // Then: Kein Fehler STRUCTURE_027 + assertFalse(result.getErrors().stream() + .anyMatch(error -> "STRUCTURE_027".equals(error.errorCode())), + "STRUCTURE_027 sollte nicht auftreten bei 99 FHL"); + } + + @Test + void validate_shouldReportErrorForAsvfehWith100Fhl() { + // Given: ASVFEH mit genau 100 FHL + List segments = new ArrayList<>(); + segments.add(new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVFEH:D:03B:UN:EAN008")))); + for (int i = 0; i < 100; i++) { + segments.add(new Segment("FHL", i + 2, List.of(new Field(1, String.valueOf(i + 1))))); + } + segments.add(new Segment("UNT", 102, List.of(new Field(1, "102"), new Field(2, "12345")))); + Message message = new Message(1, segments); + InputFile inputFile = new InputFile("test.txt", List.of(message)); + + // When + ValidationResult result = validator.validate(inputFile); + + // Then: Genau ein Fehler STRUCTURE_027 + assertTrue(result.hasErrors(), "Es sollte einen Fehler geben"); + assertEquals(1, result.getErrors().size(), "Es sollte genau einen Fehler geben"); + + ValidationError error = result.getErrors().get(0); + assertEquals("STRUCTURE_027", error.errorCode()); + assertEquals("ASVFEH-Nachricht darf FHL höchstens 99-mal enthalten", error.description()); + assertEquals("FHL", error.segmentName()); + assertEquals(1, error.segmentPosition()); + assertEquals("FHL darf maximal 99-mal vorkommen", error.expectedRule()); + } + + @Test + void validate_shouldNotReportErrorForAsvrecWith100Fhl() { + // Given: ASVREC mit 100 FHL (sollte keinen Fehler durch diese Regel erzeugen) + List segments = new ArrayList<>(); + segments.add(new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVREC:D:03B:UN:EAN008")))); + for (int i = 0; i < 100; i++) { + segments.add(new Segment("FHL", i + 2, List.of(new Field(1, String.valueOf(i + 1))))); + } + segments.add(new Segment("UNT", 102, List.of(new Field(1, "102"), new Field(2, "12345")))); + Message message = new Message(1, segments); + InputFile inputFile = new InputFile("test.txt", List.of(message)); + + // When + ValidationResult result = validator.validate(inputFile); + + // Then: Kein Fehler STRUCTURE_027 (Regel gilt nur für ASVFEH) + assertFalse(result.getErrors().stream() + .anyMatch(error -> "STRUCTURE_027".equals(error.errorCode())), + "STRUCTURE_027 sollte nicht auftreten für ASVREC"); + } } \ No newline at end of file