UNH-Nachrichtentyp in Testressourcen auf ASVREC umstellen

This commit is contained in:
2026-03-26 18:08:54 +01:00
parent f082289a01
commit 069a9cf54a
14 changed files with 273 additions and 125 deletions

View File

@@ -27,6 +27,7 @@ import de.gecheckt.asv.validation.model.ValidationSeverity;
* 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 * 11. UNH muss vor UNT stehen
* 12. Der Nachrichtentyp in UNH/S009/0065 darf nur ASVREC oder ASVFEH sein
*/ */
public class DefaultStructureValidator implements StructureValidator { public class DefaultStructureValidator implements StructureValidator {
@@ -95,28 +96,35 @@ public class DefaultStructureValidator implements StructureValidator {
continue; continue;
} }
// Hole die UNH- und UNT-Segmente einmalig für alle Validierungen
var unhSegment = message.getFirstSegment("UNH");
var untSegment = message.getFirstSegment("UNT");
// Merke, ob grundlegende Strukturfehler vorliegen
boolean hasBasicStructureErrors = false;
// Regel 9: Nachricht muss mindestens ein UNH-Segment enthalten // Regel 9: Nachricht muss mindestens ein UNH-Segment enthalten
validateUnhPresence(message, errors); validateUnhPresence(message, errors, unhSegment);
// Regel 10: Nachricht muss mindestens ein UNT-Segment enthalten // Regel 10: Nachricht muss mindestens ein UNT-Segment enthalten
validateUntPresence(message, errors); validateUntPresence(message, errors, untSegment);
// Regel 7: UNH- und UNT-Referenznummern müssen übereinstimmen // Prüfe, ob grundlegende Strukturfehler vorliegen
// Nur prüfen, wenn beide Segmente vorhanden sind if (unhSegment.isEmpty() || untSegment.isEmpty()) {
if (message.getFirstSegment("UNH").isPresent() && message.getFirstSegment("UNT").isPresent()) { hasBasicStructureErrors = true;
validateUnhUntReferenceNumbers(message, errors);
} }
// Regel 8: UNT-Segmentanzahl muss mit tatsächlicher Segmentanzahl übereinstimmen // Führe weitere Validierungen nur durch, wenn beide Segmente vorhanden sind
// Nur prüfen, wenn UNT-Segment vorhanden ist // und keine grundlegenden Strukturfehler vorliegen
if (message.getFirstSegment("UNT").isPresent()) { if (!hasBasicStructureErrors && unhSegment.isPresent() && untSegment.isPresent()) {
validateUntSegmentCount(message, errors); // Regel 7: UNH- und UNT-Referenznummern müssen übereinstimmen
} validateUnhUntReferenceNumbers(message, errors, unhSegment.get(), untSegment.get());
// Regel 11: UNH muss vor UNT stehen // Regel 11: UNH muss vor UNT stehen
// Nur prüfen, wenn beide Segmente vorhanden sind validateUnhBeforeUnt(message, errors, unhSegment.get(), untSegment.get());
if (message.getFirstSegment("UNH").isPresent() && message.getFirstSegment("UNT").isPresent()) {
validateUnhBeforeUnt(message, errors); // Regel 8: UNT-Segmentanzahl muss mit tatsächlicher Segmentanzahl übereinstimmen
validateUntSegmentCount(message, errors, untSegment.get());
} }
} }
} }
@@ -126,10 +134,10 @@ public class DefaultStructureValidator implements StructureValidator {
* *
* @param message die zu validierende Nachricht * @param message die zu validierende Nachricht
* @param errors die Liste zum Hinzufügen von Validierungsfehlern * @param errors die Liste zum Hinzufügen von Validierungsfehlern
* @param unhSegment das UNH-Segment der Nachricht (kann leer sein)
*/ */
private void validateUnhPresence(Message message, List<ValidationError> errors) { private void validateUnhPresence(Message message, List<ValidationError> errors,
var unhSegment = message.getFirstSegment("UNH"); java.util.Optional<Segment> unhSegment) {
// Wenn kein UNH-Segment vorhanden ist, Fehler hinzufügen // Wenn kein UNH-Segment vorhanden ist, Fehler hinzufügen
if (unhSegment.isEmpty()) { if (unhSegment.isEmpty()) {
errors.add(createError( errors.add(createError(
@@ -144,6 +152,47 @@ public class DefaultStructureValidator implements StructureValidator {
"UNH-Segment erforderlich" "UNH-Segment erforderlich"
)); ));
} }
// Wenn UNH-Segment vorhanden ist, prüfe den Nachrichtentyp
else {
validateMessageType(unhSegment.get(), message.messagePosition(), errors);
}
}
/**
* Validiert den Nachrichtentyp im UNH-Segment.
*
* @param unhSegment das UNH-Segment
* @param messagePosition die Position der Nachricht
* @param errors die Liste zum Hinzufügen von Validierungsfehlern
*/
private void validateMessageType(Segment unhSegment, int messagePosition, List<ValidationError> errors) {
// Prüfe, ob das zweite Feld nach dem Segmentnamen vorhanden ist
if (unhSegment.fields().size() >= 2) {
var messageTypeField = unhSegment.fields().get(1); // S009 composite element
var rawValue = messageTypeField.rawValue();
// Extrahiere den Nachrichtentyp vor dem ersten ':'
String messageType = rawValue;
int colonIndex = rawValue.indexOf(':');
if (colonIndex > 0) {
messageType = rawValue.substring(0, colonIndex);
}
// Prüfe, ob der Nachrichtentyp gültig ist
if (!"ASVREC".equals(messageType) && !"ASVFEH".equals(messageType)) {
errors.add(createError(
"STRUCTURE_012",
"Ungültiger Nachrichtentyp in UNH/S009/0065: " + messageType,
ValidationSeverity.ERROR,
"UNH",
messagePosition,
"S009/0065",
2,
messageType,
"Nachrichtentyp muss ASVREC oder ASVFEH sein"
));
}
}
} }
/** /**
@@ -151,10 +200,10 @@ public class DefaultStructureValidator implements StructureValidator {
* *
* @param message die zu validierende Nachricht * @param message die zu validierende Nachricht
* @param errors die Liste zum Hinzufügen von Validierungsfehlern * @param errors die Liste zum Hinzufügen von Validierungsfehlern
* @param untSegment das UNT-Segment der Nachricht (kann leer sein)
*/ */
private void validateUntPresence(Message message, List<ValidationError> errors) { private void validateUntPresence(Message message, List<ValidationError> errors,
var untSegment = message.getFirstSegment("UNT"); java.util.Optional<Segment> untSegment) {
// Wenn kein UNT-Segment vorhanden ist, Fehler hinzufügen // Wenn kein UNT-Segment vorhanden ist, Fehler hinzufügen
if (untSegment.isEmpty()) { if (untSegment.isEmpty()) {
errors.add(createError( errors.add(createError(
@@ -176,40 +225,36 @@ public class DefaultStructureValidator implements StructureValidator {
* *
* @param message die zu validierende Nachricht * @param message die zu validierende Nachricht
* @param errors die Liste zum Hinzufügen von Validierungsfehlern * @param errors die Liste zum Hinzufügen von Validierungsfehlern
* @param untSegment das UNT-Segment
*/ */
private void validateUntSegmentCount(Message message, List<ValidationError> errors) { private void validateUntSegmentCount(Message message, List<ValidationError> errors, Segment untSegment) {
var untSegment = message.getFirstSegment("UNT"); var fields = untSegment.fields();
// Nur prüfen, wenn UNT-Segment vorhanden ist // Prüfen, ob das erste Feld (Segmentanzahl) vorhanden ist
if (untSegment.isPresent()) { if (!fields.isEmpty()) {
var fields = untSegment.get().fields(); var countField = fields.get(0); // 0074 - Anzahl der Segmente
var countValue = countField.rawValue();
// Prüfen, ob das erste Feld (Segmentanzahl) vorhanden ist // Nur prüfen, wenn der Wert numerisch interpretiert werden kann
if (!fields.isEmpty()) { try {
var countField = fields.get(0); // 0074 - Anzahl der Segmente int declaredCount = Integer.parseInt(countValue);
var countValue = countField.rawValue(); int actualCount = message.segments().size();
// Nur prüfen, wenn der Wert numerisch interpretiert werden kann if (declaredCount != actualCount) {
try { errors.add(createError(
int declaredCount = Integer.parseInt(countValue); "STRUCTURE_008",
int actualCount = message.segments().size(); "Die im UNT angegebene Segmentanzahl entspricht nicht der tatsächlichen Anzahl",
ValidationSeverity.ERROR,
if (declaredCount != actualCount) { "UNT",
errors.add(createError( message.messagePosition(),
"STRUCTURE_008", "0074",
"Die im UNT angegebene Segmentanzahl entspricht nicht der tatsächlichen Anzahl", 1,
ValidationSeverity.ERROR, declaredCount + " != " + actualCount,
"UNT", "Segmentanzahl in UNT muss mit tatsächlicher Anzahl übereinstimmen"
message.messagePosition(), ));
"0074",
1,
declaredCount + " != " + actualCount,
"Segmentanzahl in UNT muss mit tatsächlicher Anzahl übereinstimmen"
));
}
} catch (NumberFormatException e) {
// Nicht-numerischer Wert - keine zusätzliche Fehlermeldung gemäß Anforderung
} }
} catch (NumberFormatException e) {
// Nicht-numerischer Wert - keine zusätzliche Fehlermeldung gemäß Anforderung
} }
} }
} }
@@ -219,30 +264,27 @@ public class DefaultStructureValidator implements StructureValidator {
* *
* @param message die zu validierende Nachricht * @param message die zu validierende Nachricht
* @param errors die Liste zum Hinzufügen von Validierungsfehlern * @param errors die Liste zum Hinzufügen von Validierungsfehlern
* @param unhSegment das UNH-Segment
* @param untSegment das UNT-Segment
*/ */
private void validateUnhBeforeUnt(Message message, List<ValidationError> errors) { private void validateUnhBeforeUnt(Message message, List<ValidationError> errors,
var unhSegment = message.getFirstSegment("UNH"); Segment unhSegment, Segment untSegment) {
var untSegment = message.getFirstSegment("UNT"); int unhPosition = unhSegment.segmentPosition();
int untPosition = untSegment.segmentPosition();
// Prüft, ob beide Segmente vorhanden sind, bevor eine Validierung erfolgt // UNH muss vor UNT stehen
if (unhSegment.isPresent() && untSegment.isPresent()) { if (unhPosition > untPosition) {
int unhPosition = unhSegment.get().segmentPosition(); errors.add(createError(
int untPosition = untSegment.get().segmentPosition(); "STRUCTURE_011",
"UNH muss vor UNT stehen",
// UNH muss vor UNT stehen ValidationSeverity.ERROR,
if (unhPosition > untPosition) { "UNH/UNT",
errors.add(createError( message.messagePosition(),
"STRUCTURE_011", "",
"UNH muss vor UNT stehen", 0,
ValidationSeverity.ERROR, "UNH at position " + unhPosition + ", UNT at position " + untPosition,
"UNH/UNT", "UNH muss vor UNT stehen"
message.messagePosition(), ));
"",
0,
"UNH at position " + unhPosition + ", UNT at position " + untPosition,
"UNH muss vor UNT stehen"
));
}
} }
} }
@@ -251,42 +293,39 @@ public class DefaultStructureValidator implements StructureValidator {
* *
* @param message die zu validierende Nachricht * @param message die zu validierende Nachricht
* @param errors die Liste zum Hinzufügen von Validierungsfehlern * @param errors die Liste zum Hinzufügen von Validierungsfehlern
* @param unhSegment das UNH-Segment
* @param untSegment das UNT-Segment
*/ */
private void validateUnhUntReferenceNumbers(Message message, List<ValidationError> errors) { private void validateUnhUntReferenceNumbers(Message message, List<ValidationError> errors,
var unhSegment = message.getFirstSegment("UNH"); Segment unhSegment, Segment untSegment) {
var untSegment = message.getFirstSegment("UNT"); var unhFields = unhSegment.fields();
var untFields = untSegment.fields();
// Prüft, ob beide Segmente vorhanden sind, bevor eine Validierung erfolgt // UNH-Referenznummer ist im 1. Feld (erstes Feld nach dem Segmentnamen)
if (unhSegment.isPresent() && untSegment.isPresent()) { // UNT-Referenznummer ist im 2. Feld (zweites Feld nach dem Segmentnamen)
var unhFields = unhSegment.get().fields(); if (!unhFields.isEmpty() && untFields.size() >= 2) {
var untFields = untSegment.get().fields(); var unhReference = unhFields.get(0).rawValue();
var untReference = untFields.get(1).rawValue();
// UNH-Referenznummer ist im 1. Feld (erstes Feld nach dem Segmentnamen) // Entferne möglicherweise vorhandenes abschließendes Hochkomma bei untReference
// UNT-Referenznummer ist im 2. Feld (zweites Feld nach dem Segmentnamen) String normalizedUntReference = untReference;
if (!unhFields.isEmpty() && untFields.size() >= 2) { if (untReference.endsWith("'")) {
var unhReference = unhFields.get(0).rawValue(); normalizedUntReference = untReference.substring(0, untReference.length() - 1);
var untReference = untFields.get(1).rawValue(); }
// Entferne möglicherweise vorhandenes abschließendes Hochkomma bei untReference // Vergleiche die Referenznummern
String normalizedUntReference = untReference; if (!unhReference.equals(normalizedUntReference)) {
if (untReference.endsWith("'")) { errors.add(createError(
normalizedUntReference = untReference.substring(0, untReference.length() - 1); "STRUCTURE_007",
} "UNH- und UNT-Referenznummern stimmen nicht überein",
ValidationSeverity.ERROR,
// Vergleiche die Referenznummern "UNH/UNT",
if (!unhReference.equals(normalizedUntReference)) { message.messagePosition(),
errors.add(createError( "",
"STRUCTURE_007", 0,
"UNH- und UNT-Referenznummern stimmen nicht überein", unhReference + " != " + normalizedUntReference,
ValidationSeverity.ERROR, "Referenznummern in UNH und UNT müssen übereinstimmen"
"UNH/UNT", ));
message.messagePosition(),
"",
0,
unhReference + " != " + normalizedUntReference,
"Referenznummern in UNH und UNT müssen übereinstimmen"
));
}
} }
} }
} }

View File

@@ -75,7 +75,7 @@ class DefaultStructureValidatorTest {
void validate_shouldReportErrorWhenSegmentHasDuplicatePositions() { void validate_shouldReportErrorWhenSegmentHasDuplicatePositions() {
// Manually create segments with duplicate positions to bypass parser validation // Manually create segments with duplicate positions to bypass parser validation
// Also include required UNH and UNT segments // Also include required UNH and UNT segments
Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ORDERS:D:03B:UN:EAN008"))); Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVREC:D:03B:UN:EAN008")));
Segment segment1 = new Segment("SEG1", 2); Segment segment1 = new Segment("SEG1", 2);
Segment segment2 = new Segment("SEG2", 2); // Duplicate position Segment segment2 = new Segment("SEG2", 2); // Duplicate position
Segment unt = new Segment("UNT", 4, List.of(new Field(1, "4"), new Field(2, "12345"))); Segment unt = new Segment("UNT", 4, List.of(new Field(1, "4"), new Field(2, "12345")));
@@ -100,7 +100,7 @@ class DefaultStructureValidatorTest {
void validate_shouldReportErrorWhenFieldHasDuplicatePositions() { void validate_shouldReportErrorWhenFieldHasDuplicatePositions() {
// Create segments with duplicate field positions manually to bypass parser validation // Create segments with duplicate field positions manually to bypass parser validation
// Also include required UNH and UNT segments // Also include required UNH and UNT segments
Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ORDERS:D:03B:UN:EAN008"))); Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVREC:D:03B:UN:EAN008")));
Field field1 = new Field(1, "value1"); Field field1 = new Field(1, "value1");
Field field2 = new Field(1, "value2"); // Duplicate position Field field2 = new Field(1, "value2"); // Duplicate position
Segment segment = new Segment("SEG1", 2, List.of(field1, field2)); Segment segment = new Segment("SEG1", 2, List.of(field1, field2));

View File

@@ -0,0 +1,116 @@
package de.gecheckt.asv.validation.structure;
import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
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.parser.DefaultInputFileParser;
import de.gecheckt.asv.parser.DefaultSegmentLineTokenizer;
import de.gecheckt.asv.parser.InputFileParseException;
import de.gecheckt.asv.parser.SegmentLineTokenizer;
import de.gecheckt.asv.validation.model.ValidationError;
import de.gecheckt.asv.validation.model.ValidationResult;
class DefaultStructureValidatorTestAdditional {
private DefaultStructureValidator validator;
@BeforeEach
void setUp() {
validator = new DefaultStructureValidator();
}
@Test
void validate_shouldNotReportErrorWhenMessageTypeIsASVREC() {
// Given
Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "ASVREC: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));
InputFile inputFile = new InputFile("test.txt", List.of(message));
// When
ValidationResult result = validator.validate(inputFile);
// Then
// Should not have STRUCTURE_012 error for valid ASVREC message type
assertFalse(result.getErrors().stream()
.anyMatch(error -> "STRUCTURE_012".equals(error.errorCode())));
assertFalse(result.hasErrors(), "There should be no validation errors for valid ASVREC message type");
}
@Test
void validate_shouldNotReportErrorWhenMessageTypeIsASVFEH() {
// Given
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));
InputFile inputFile = new InputFile("test.txt", List.of(message));
// When
ValidationResult result = validator.validate(inputFile);
// Then
// Should not have STRUCTURE_012 error for valid ASVFEH message type
assertFalse(result.getErrors().stream()
.anyMatch(error -> "STRUCTURE_012".equals(error.errorCode())));
assertFalse(result.hasErrors(), "There should be no validation errors for valid ASVFEH message type");
}
@Test
void validate_shouldReportErrorWhenMessageTypeIsInvalid() {
// Given
Segment unh = new Segment("UNH", 1, List.of(new Field(1, "12345"), new Field(2, "INVALID: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));
InputFile inputFile = new InputFile("test.txt", List.of(message));
// When
ValidationResult result = validator.validate(inputFile);
// Then
assertTrue(result.hasErrors());
assertEquals(1, result.getErrors().size());
ValidationError error = result.getErrors().get(0);
assertEquals("STRUCTURE_012", error.errorCode());
assertEquals("Ungültiger Nachrichtentyp in UNH/S009/0065: INVALID", error.description());
assertEquals("UNH", error.segmentName());
assertEquals(1, error.segmentPosition());
assertEquals("S009/0065", error.fieldName());
assertEquals(2, error.fieldPosition());
assertEquals("INVALID", error.actualValue());
assertEquals("Nachrichtentyp muss ASVREC oder ASVFEH sein", error.expectedRule());
}
@Test
void validate_shouldNotReportAdditionalErrorWhenUnhIsMissing() 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_012 error for missing UNH
assertFalse(result.getErrors().stream()
.anyMatch(error -> "STRUCTURE_012".equals(error.errorCode())));
// Should have exactly one error for missing UNH (STRUCTURE_009)
assertEquals(1, result.getErrors().size(), "Should have exactly one error for missing UNH");
assertEquals("STRUCTURE_009", result.getErrors().get(0).errorCode(), "Error should be STRUCTURE_009 for missing UNH");
}
}

View File

@@ -1,3 +0,0 @@
UNH+12345+ORDERS:D:03B:UN:EAN008'
SEG1+value1+value1'
UNT+3+12345'

View File

@@ -1,4 +0,0 @@
UNH+12345+ORDERS:D:03B:UN:EAN008'
SEG1+value1+value2'
SEG2+value3+value4'
UNT+3+12345'

View File

@@ -1,4 +1,4 @@
UNH+12345+ORDERS:D:03B:UN:EAN008' UNH+12345+ASVREC:D:03B:UN:EAN008'
BGM+220+100001' BGM+220+100001'
DTM+137:20260325:102' DTM+137:20260325:102'
NAD+BY+5000000000000:16++Customer Name' NAD+BY+5000000000000:16++Customer Name'

View File

@@ -1,4 +1,4 @@
UNH+12345+ORDERS:D:03B:UN:EAN008' UNH+12345+ASVREC:D:03B:UN:EAN008'
BGM+220+100001' BGM+220+100001'
DTM+137:20260325:102' DTM+137:20260325:102'
NAD+BY+5000000000000:16++Customer Name' NAD+BY+5000000000000:16++Customer Name'

View File

@@ -1,4 +1,4 @@
UNH+12345+ORDERS:D:03B:UN:EAN008' UNH+12345+ASVREC:D:03B:UN:EAN008'
BGM+220+100001' BGM+220+100001'
DTM+137:20260325:102' DTM+137:20260325:102'
NAD+BY+5000000000000:16++Customer Name' NAD+BY+5000000000000:16++Customer Name'

View File

@@ -1,4 +1,4 @@
UNH+12345+ORDERS:D:03B:UN:EAN008' UNH+12345+ASVREC:D:03B:UN:EAN008'
BGM+220+100001' BGM+220+100001'
DTM+137:20260325:102' DTM+137:20260325:102'
NAD+BY+5000000000000:16++Customer Name' NAD+BY+5000000000000:16++Customer Name'

View File

@@ -1,4 +1,4 @@
UNH+1+ORDERS:D:03B:UN:EAN008' UNH+1+ASVREC:D:03B:UN:EAN008'
BGM+220+100001' BGM+220+100001'
DTM+137:20260325:102' DTM+137:20260325:102'
NAD+BY+5000000000000:16++Customer Name' NAD+BY+5000000000000:16++Customer Name'
@@ -6,4 +6,4 @@ LIN+1++Product123:SA'
QTY+21:10:PCE' QTY+21:10:PCE'
UNS+S' UNS+S'
CNT+2:1' CNT+2:1'
UNT+8+1' UNT+9+1'

View File

@@ -1,4 +1,4 @@
UNH+12345+ORDERS:D:03B:UN:EAN008' UNH+12345+ASVREC:D:03B:UN:EAN008'
BGM+220+100001' BGM+220+100001'
DTM+137:20260325:102' DTM+137:20260325:102'
NAD+BY+5000000000000:16++Customer Name' NAD+BY+5000000000000:16++Customer Name'

View File

@@ -1,4 +1,4 @@
UNH+12345+ORDERS:D:03B:UN:EAN008' UNH+12345+ASVREC:D:03B:UN:EAN008'
BGM+220+100001' BGM+220+100001'
DTM+137:20260325:102' DTM+137:20260325:102'
NAD+BY+5000000000000:16++Customer Name' NAD+BY+5000000000000:16++Customer Name'

View File

@@ -6,4 +6,4 @@ LIN+1++Product123:SA'
QTY+21:10:PCE' QTY+21:10:PCE'
UNS+S' UNS+S'
CNT+2:1' CNT+2:1'
UNH+1+ORDERS:D:03B:UN:EAN008' UNH+1+ASVREC:D:03B:UN:EAN008'

View File

@@ -1,4 +1,4 @@
UNH+12345+ORDERS:D:03B:UN:EAN008' UNH+12345+ASVREC:D:03B:UN:EAN008'
BGM+220+100001' BGM+220+100001'
DTM+137:20260325:102' DTM+137:20260325:102'
NAD+BY+5000000000000:16++Customer Name' NAD+BY+5000000000000:16++Customer Name'