FHL-Pflichtsegment für ASVFEH validieren
This commit is contained in:
@@ -34,6 +34,7 @@ import de.gecheckt.asv.validation.model.ValidationSeverity;
|
||||
* 16. Für ASVREC mit Rechnungskennzeichen "1" in REA dürfen DGN und LEA nicht vorhanden sein
|
||||
* 17. Für ASVREC mit Rechnungskennzeichen "1" in REA muss der Rechnungsbetrag "0,00" sein
|
||||
* 18. Für ASVREC müssen IFA, REA und IVA jeweils genau einmal vorkommen
|
||||
* 19. Für ASVFEH-Nachrichten muss mindestens ein FHL-Segment vorhanden sein
|
||||
*/
|
||||
public class DefaultStructureValidator implements StructureValidator {
|
||||
|
||||
@@ -146,6 +147,9 @@ public class DefaultStructureValidator implements StructureValidator {
|
||||
|
||||
// Neue Regel: Für ASVREC müssen IFA, REA und IVA jeweils genau einmal vorkommen
|
||||
validateAsvrecSegmentCardinality(message, errors);
|
||||
|
||||
// Neue Regel: Für ASVFEH-Nachrichten muss mindestens ein FHL-Segment vorhanden sein
|
||||
validateAsvfehRequiredFhlSegment(message, errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -529,7 +533,9 @@ public class DefaultStructureValidator implements StructureValidator {
|
||||
if (unhSegment.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!"ASVREC".equals(extractMessageType(unhSegment.get()))) {
|
||||
String messageType = extractMessageType(unhSegment.get());
|
||||
// Nur für ASVREC-Nachrichten prüfen
|
||||
if (!"ASVREC".equals(messageType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -594,7 +600,9 @@ public class DefaultStructureValidator implements StructureValidator {
|
||||
if (unhSegment.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!"ASVREC".equals(extractMessageType(unhSegment.get()))) {
|
||||
String messageType = extractMessageType(unhSegment.get());
|
||||
// Nur für ASVREC-Nachrichten prüfen
|
||||
if (!"ASVREC".equals(messageType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -689,7 +697,9 @@ public class DefaultStructureValidator implements StructureValidator {
|
||||
if (unhSegment.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!"ASVREC".equals(extractMessageType(unhSegment.get()))) {
|
||||
String messageType = extractMessageType(unhSegment.get());
|
||||
// Nur für ASVREC-Nachrichten prüfen
|
||||
if (!"ASVREC".equals(messageType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -738,7 +748,9 @@ public class DefaultStructureValidator implements StructureValidator {
|
||||
if (unhSegment.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!"ASVREC".equals(extractMessageType(unhSegment.get()))) {
|
||||
String messageType = extractMessageType(unhSegment.get());
|
||||
// Nur für ASVREC-Nachrichten prüfen
|
||||
if (!"ASVREC".equals(messageType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -787,6 +799,38 @@ public class DefaultStructureValidator implements StructureValidator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validiert, dass für ASVFEH-Nachrichten mindestens ein FHL-Segment vorhanden ist.
|
||||
*
|
||||
* @param message die zu validierende Nachricht
|
||||
* @param errors die Liste zum Hinzufügen von Validierungsfehlern
|
||||
*/
|
||||
private void validateAsvfehRequiredFhlSegment(Message message, List<ValidationError> errors) {
|
||||
// Prüfe den Nachrichtentyp aus dem UNH-Segment
|
||||
var unhSegment = message.getFirstSegment("UNH");
|
||||
if (unhSegment.isPresent()) {
|
||||
String messageType = extractMessageType(unhSegment.get());
|
||||
|
||||
// Nur für ASVFEH-Nachrichten prüfen
|
||||
if ("ASVFEH".equals(messageType)) {
|
||||
// Prüfe, ob mindestens ein FHL-Segment vorhanden ist
|
||||
if (message.getFirstSegment("FHL").isEmpty()) {
|
||||
errors.add(createError(
|
||||
"STRUCTURE_025",
|
||||
"ASVFEH-Nachricht muss mindestens ein FHL-Segment enthalten",
|
||||
ValidationSeverity.ERROR,
|
||||
"",
|
||||
message.messagePosition(),
|
||||
"",
|
||||
0,
|
||||
"",
|
||||
"FHL-Segment erforderlich für ASVFEH-Nachrichten"
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrahiert den Nachrichtentyp aus dem UNH-Segment.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package de.gecheckt.asv.validation.structure;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import de.gecheckt.asv.domain.model.Field;
|
||||
import de.gecheckt.asv.domain.model.InputFile;
|
||||
import de.gecheckt.asv.domain.model.Message;
|
||||
import de.gecheckt.asv.domain.model.Segment;
|
||||
import de.gecheckt.asv.validation.model.ValidationError;
|
||||
import de.gecheckt.asv.validation.model.ValidationResult;
|
||||
|
||||
/**
|
||||
* Testfälle für die Validierung der Mindestpräsenz des FHL-Segments in ASVFEH-Nachrichten.
|
||||
*
|
||||
* Testet spezifisch die neue Regel:
|
||||
* Für ASVFEH-Nachrichten muss mindestens ein FHL-Segment vorhanden sein.
|
||||
*/
|
||||
class DefaultStructureValidatorAsvfehFhlSegmentTest {
|
||||
|
||||
private DefaultStructureValidator validator;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
validator = new DefaultStructureValidator();
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_shouldNotReportErrorForAsvfehWithOneFhlSegment() {
|
||||
// Given: ASVFEH-Nachricht mit einem FHL-Segment
|
||||
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_025
|
||||
assertFalse(result.hasErrors(), "Es sollte keine Fehler geben");
|
||||
assertTrue(result.getErrors().stream()
|
||||
.noneMatch(error -> "STRUCTURE_025".equals(error.errorCode())),
|
||||
"STRUCTURE_025 Fehler sollte nicht auftreten");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_shouldNotReportErrorForAsvfehWithMultipleFhlSegments() {
|
||||
// Given: ASVFEH-Nachricht mit mehreren FHL-Segmenten
|
||||
Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVFEH:D:03B:UN:EAN008")));
|
||||
Segment fhl1 = new Segment("FHL", 2, List.of(new Field(1, "1")));
|
||||
Segment fhl2 = new Segment("FHL", 3, List.of(new Field(1, "2")));
|
||||
Segment unt = new Segment("UNT", 4, List.of(new Field(1, "4"), new Field(2, "12345")));
|
||||
Message message = new Message(1, List.of(unh, fhl1, fhl2, unt));
|
||||
InputFile inputFile = new InputFile("test.txt", List.of(message));
|
||||
|
||||
// When
|
||||
ValidationResult result = validator.validate(inputFile);
|
||||
|
||||
// Then: Kein Fehler STRUCTURE_025
|
||||
assertFalse(result.hasErrors(), "Es sollte keine Fehler geben");
|
||||
assertTrue(result.getErrors().stream()
|
||||
.noneMatch(error -> "STRUCTURE_025".equals(error.errorCode())),
|
||||
"STRUCTURE_025 Fehler sollte nicht auftreten");
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_shouldReportErrorForAsvfehWithoutFhlSegment() {
|
||||
// Given: ASVFEH-Nachricht ohne FHL-Segment
|
||||
Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVFEH:D:03B:UN:EAN008")));
|
||||
Segment seg = new Segment("SEG", 2, List.of(new Field(1, "value")));
|
||||
Segment unt = new Segment("UNT", 3, List.of(new Field(1, "3"), new Field(2, "12345")));
|
||||
Message message = new Message(1, List.of(unh, seg, unt));
|
||||
InputFile inputFile = new InputFile("test.txt", List.of(message));
|
||||
|
||||
// When
|
||||
ValidationResult result = validator.validate(inputFile);
|
||||
|
||||
// Then: Genau ein Fehler STRUCTURE_025
|
||||
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_025", error.errorCode());
|
||||
assertEquals("ASVFEH-Nachricht muss mindestens ein FHL-Segment enthalten", error.description());
|
||||
assertEquals("", error.segmentName());
|
||||
assertEquals(1, error.segmentPosition());
|
||||
assertEquals("FHL-Segment erforderlich für ASVFEH-Nachrichten", error.expectedRule());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_shouldNotReportErrorForAsvrecWithoutFhlSegment() {
|
||||
// Given: ASVREC-Nachricht ohne FHL-Segment (sollte keinen Fehler erzeugen)
|
||||
Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVREC:D:03B:UN:EAN008")));
|
||||
Segment ifa = new Segment("IFA", 2);
|
||||
Segment rea = new Segment("REA", 3);
|
||||
Segment iva = new Segment("IVA", 4);
|
||||
Segment unt = new Segment("UNT", 5, List.of(new Field(1, "5"), new Field(2, "12345")));
|
||||
Message message = new Message(1, List.of(unh, ifa, rea, iva, unt));
|
||||
InputFile inputFile = new InputFile("test.txt", List.of(message));
|
||||
|
||||
// When
|
||||
ValidationResult result = validator.validate(inputFile);
|
||||
|
||||
// Then: Kein Fehler STRUCTURE_025
|
||||
assertFalse(result.getErrors().stream()
|
||||
.anyMatch(error -> "STRUCTURE_025".equals(error.errorCode())),
|
||||
"STRUCTURE_025 Fehler sollte nicht auftreten für ASVREC");
|
||||
}
|
||||
}
|
||||
@@ -213,7 +213,7 @@ class DefaultStructureValidatorAsvrecRechnungskennzeichenTest {
|
||||
|
||||
@Test
|
||||
void validate_asvfeh_keineRechnungskennzeichenRegel() {
|
||||
// ASVFEH mit REA Kennzeichen "0" und ohne DGN/LEA -> kein STRUCTURE_017/018
|
||||
// ASVFEH mit REA Kennzeichen "0", FHL und ohne DGN/LEA -> kein STRUCTURE_017/018
|
||||
Segment unh = new Segment("UNH", 1,
|
||||
List.of(new Field(1, "12345"), new Field(2, "ASVFEH:D:03B:UN:EAN008")));
|
||||
Segment rea = new Segment("REA", 2, List.of(
|
||||
@@ -222,9 +222,10 @@ class DefaultStructureValidatorAsvrecRechnungskennzeichenTest {
|
||||
new Field(3, "RNR-001"),
|
||||
new Field(4, "0")
|
||||
));
|
||||
Segment unt = new Segment("UNT", 3,
|
||||
List.of(new Field(1, "3"), new Field(2, "12345")));
|
||||
Message message = new Message(1, List.of(unh, rea, unt));
|
||||
Segment fhl = new Segment("FHL", 3, List.of(new Field(1, "1")));
|
||||
Segment unt = new Segment("UNT", 4,
|
||||
List.of(new Field(1, "4"), new Field(2, "12345")));
|
||||
Message message = new Message(1, List.of(unh, rea, fhl, unt));
|
||||
InputFile inputFile = new InputFile("test.txt", List.of(message));
|
||||
|
||||
ValidationResult result = validator.validate(inputFile);
|
||||
|
||||
@@ -259,10 +259,11 @@ class DefaultStructureValidatorAsvrecSegmentCardinalityTest {
|
||||
Segment rea2 = new Segment("REA", 5);
|
||||
Segment iva1 = new Segment("IVA", 6);
|
||||
Segment iva2 = new Segment("IVA", 7);
|
||||
Segment unt = new Segment("UNT", 8,
|
||||
List.of(new Field(1, "8"), new Field(2, "12345")));
|
||||
Segment fhl = new Segment("FHL", 8, List.of(new Field(1, "1")));
|
||||
Segment unt = new Segment("UNT", 9,
|
||||
List.of(new Field(1, "9"), new Field(2, "12345")));
|
||||
|
||||
Message message = new Message(1, List.of(unh, ifa1, ifa2, rea1, rea2, iva1, iva2, unt));
|
||||
Message message = new Message(1, List.of(unh, ifa1, ifa2, rea1, rea2, iva1, iva2, fhl, unt));
|
||||
InputFile inputFile = new InputFile("test.txt", List.of(message));
|
||||
|
||||
ValidationResult result = validator.validate(inputFile);
|
||||
|
||||
@@ -131,15 +131,16 @@ class DefaultStructureValidatorAsvrecSegmentOrderTest {
|
||||
|
||||
@Test
|
||||
void validate_shouldNotReportOrderErrorForAsvfeh() {
|
||||
// ASVFEH mit umgekehrter Reihenfolge der Segmente -> kein STRUCTURE_016
|
||||
// ASVFEH mit umgekehrter Reihenfolge der Segmente und FHL -> kein STRUCTURE_016
|
||||
Segment unh = new Segment("UNH", 1,
|
||||
List.of(new Field(1, "12345"), new Field(2, "ASVFEH:D:03B:UN:EAN008")));
|
||||
Segment iva = new Segment("IVA", 2);
|
||||
Segment rea = new Segment("REA", 3);
|
||||
Segment ifa = new Segment("IFA", 4);
|
||||
Segment unt = new Segment("UNT", 5,
|
||||
List.of(new Field(1, "5"), new Field(2, "12345")));
|
||||
Message message = new Message(1, List.of(unh, iva, rea, ifa, unt));
|
||||
Segment fhl = new Segment("FHL", 5, List.of(new Field(1, "1")));
|
||||
Segment unt = new Segment("UNT", 6,
|
||||
List.of(new Field(1, "6"), new Field(2, "12345")));
|
||||
Message message = new Message(1, List.of(unh, iva, rea, ifa, fhl, unt));
|
||||
InputFile inputFile = new InputFile("test.txt", List.of(message));
|
||||
|
||||
ValidationResult result = validator.validate(inputFile);
|
||||
|
||||
@@ -168,10 +168,11 @@ class DefaultStructureValidatorAsvrecSegmentsTest {
|
||||
|
||||
@Test
|
||||
void validate_shouldNotReportErrorForAsvfehWithoutIfaReaIvaSegments() {
|
||||
// Given
|
||||
// Given: ASVFEH mit FHL, aber ohne IFA/REA/IVA
|
||||
Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVFEH:D:03B:UN:EAN008")));
|
||||
Segment unt = new Segment("UNT", 2, List.of(new Field(1, "2"), new Field(2, "12345")));
|
||||
Message message = new Message(1, List.of(unh, unt));
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user