Reihenfolge von UNH und UNT pro Nachricht validieren

This commit is contained in:
2026-03-26 10:51:40 +01:00
parent f7af574a97
commit d35e2f1df0
4 changed files with 140 additions and 0 deletions

View File

@@ -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 * 8. Die im UNT angegebene Segmentanzahl muss der tatsächlichen Anzahl der Segmente entsprechen
* 9. Eine Nachricht muss mindestens ein UNH-Segment enthalten * 9. Eine Nachricht muss mindestens ein UNH-Segment enthalten
* 10. Eine Nachricht muss mindestens ein UNT-Segment enthalten * 10. Eine Nachricht muss mindestens ein UNT-Segment enthalten
* 11. UNH muss vor UNT stehen
*/ */
public class DefaultStructureValidator implements StructureValidator { public class DefaultStructureValidator implements StructureValidator {
@@ -111,6 +112,12 @@ public class DefaultStructureValidator implements StructureValidator {
if (message.getFirstSegment("UNT").isPresent()) { if (message.getFirstSegment("UNT").isPresent()) {
validateUntSegmentCount(message, errors); 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<ValidationError> 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. * Validiert, dass die Referenznummern in UNH und UNT übereinstimmen.
* *

View File

@@ -438,4 +438,87 @@ class DefaultStructureValidatorTest {
assertFalse(result.getErrors().stream() assertFalse(result.getErrors().stream()
.anyMatch(error -> "STRUCTURE_008".equals(error.errorCode()))); .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())));
}
} }

View File

@@ -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'

View File

@@ -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'