std.edi.transport

Multimodaler Transportauftrag und Sendungsstatus per EDIFACT. Alle 8 Nachrichtentypen teilen denselben Header (EDI_TRN_HDR). IFTMIN beschreibt den vollständigen Transportauftrag mit beliebig vielen Beförderungsabschnitten (Legs). IFTDGN enthält Gefahrgutinformationen (DGD-Struct). IFTSTA übermittelt den Sendungsstatus.

  • IFTMIN (BGM 310) — Instruction for the Movement of Goods: Transportauftrag mit Legs
  • IFTMBC (BGM 311) — Response to IFTMIN: Auftragsbestätigung/-ablehnung
  • IFTMCS (BGM 312) — Instruction Contract Status: Vertragsstatus
  • IFTMAN (BGM 313) — Arrival Notice: Ankündigungsmeldung
  • IFCSUM (BGM 319) — Freight Invoice: Frachtabrechnung
  • IFTSTA (BGM 214) — Status: Sendungsstatus
  • IFTDGN (BGM 350) — Dangerous Goods Notification: Gefahrgutmeldung
  • IFTFCC (BGM 315) — Freight Costs and other Charges: Frachtkosten (Buchungsreferenz Pflicht)

IFTSTA-Statuscodes:

Konstante Wert Bedeutung
EDI_TRN_STA_PICKEDUP 1 Abgeholt
EDI_TRN_STA_INTRANSIT 2 Unterwegs
EDI_TRN_STA_DELAYED 3 Verzögert
EDI_TRN_STA_DELIVERED 4 Zugestellt

Transportmodi (IFTMIN Legs):

Wert Bedeutung
1 See
2 Schiene
3 Straße
4 Luft

import std.edi.transport;
import std.alloc;
import std.string;

fn Feld(p: int64, l: int64): pchar {
    var b: int64 := alloc(l + 1);
    var i: int64 := 0;
    while (i < l) { poke8(b + i, peek8(p + i)); i := i + 1; }
    poke8(b + l, 0);
    return b as pchar;
}

fn main(): int64 {
    var hdr: int64 := alloc(EDI_TRN_HDR_SIZE);
    var i: int64 := 0;
    while (i < EDI_TRN_HDR_SIZE) { poke8(hdr + i, 0); i := i + 1; }
    poke64(hdr + EDI_TRN_HDR_REF,        "TRP-2026-0815"c as int64);
    poke64(hdr + EDI_TRN_HDR_REFLEN,     13);
    poke64(hdr + EDI_TRN_HDR_DATE,       "20260813"c as int64);
    poke64(hdr + EDI_TRN_HDR_DATELEN,    8);
    poke64(hdr + EDI_TRN_HDR_DEPARTURE,  "CNSHA"c as int64);
    poke64(hdr + EDI_TRN_HDR_DEPLEN,     5);
    poke64(hdr + EDI_TRN_HDR_ARRIVAL,    "DEMUC"c as int64);
    poke64(hdr + EDI_TRN_HDR_ARRLEN,     5);
    poke64(hdr + EDI_TRN_HDR_CARRIER,    "Spedition Nord"c as int64);
    poke64(hdr + EDI_TRN_HDR_CARRLEN,    14);
    poke64(hdr + EDI_TRN_HDR_BOOKINGREF, "BK-99001"c as int64);
    poke64(hdr + EDI_TRN_HDR_BOOKINGLEN, 8);

    // Drei Teilstrecken: See, Bahn, Strasse
    var legs: int64 := alloc(3 * EDI_TRN_LEG_SIZE);
    i := 0;
    while (i < 3 * EDI_TRN_LEG_SIZE) { poke8(legs + i, 0); i := i + 1; }
    poke64(legs + EDI_TRN_LEG_DEPARTURE, "CNSHA"c as int64);
    poke64(legs + EDI_TRN_LEG_DEPLEN,    5);
    poke64(legs + EDI_TRN_LEG_ARRIVAL,   "DEHAM"c as int64);
    poke64(legs + EDI_TRN_LEG_ARRLEN,    5);
    poke64(legs + EDI_TRN_LEG_MODE,      1);            // 1 = See
    var g1: int64 := legs + EDI_TRN_LEG_SIZE;
    poke64(g1 + EDI_TRN_LEG_DEPARTURE, "DEHAM"c as int64);
    poke64(g1 + EDI_TRN_LEG_DEPLEN,    5);
    poke64(g1 + EDI_TRN_LEG_ARRIVAL,   "DENUE"c as int64);
    poke64(g1 + EDI_TRN_LEG_ARRLEN,    5);
    poke64(g1 + EDI_TRN_LEG_MODE,      2);              // 2 = Bahn
    var g2: int64 := legs + 2 * EDI_TRN_LEG_SIZE;
    poke64(g2 + EDI_TRN_LEG_DEPARTURE, "DENUE"c as int64);
    poke64(g2 + EDI_TRN_LEG_DEPLEN,    5);
    poke64(g2 + EDI_TRN_LEG_ARRIVAL,   "DEMUC"c as int64);
    poke64(g2 + EDI_TRN_LEG_ARRLEN,    5);
    poke64(g2 + EDI_TRN_LEG_MODE,      3);              // 3 = Strasse

    var out: int64 := alloc(4096);
    var n: int64 := EdiIftminWrite(hdr, legs, 3, out, 4096);
    PrintLn(Feld(out, n));

    var hdr2: int64 := alloc(EDI_TRN_HDR_SIZE);
    var lg2:  int64 := alloc(8 * EDI_TRN_LEG_SIZE);
    var cnt: int64 := EdiIftminRead(out, n, hdr2, lg2, 8);
    PrintLn(StrConcat("Teilstrecken: ", IntToStr(cnt)));

    // Statusmeldung: unterwegs
    poke64(hdr + EDI_TRN_HDR_STATUSCODE, EDI_IFTSTA_INTRANSIT);
    n := EdiIftstaWrite(hdr, out, 4096);
    PrintLn(Feld(out, n));
    // Pruef-Funktionen melden Fehler, nicht Erfolg: 0 = in Ordnung
    PrintLn(StrConcat("Statuspruefung (0 = ok): ", IntToStr(EdiIftstaStatusCheck(EDI_IFTSTA_INTRANSIT))));
    PrintLn(StrConcat("Statuspruefung Code 9:    ", IntToStr(EdiIftstaStatusCheck(9))));
    PrintLn(StrConcat("IFTFCC-Pruefung (0 = ok): ", IntToStr(EdiIftfccCheck(hdr))));

    // Gefahrgutmeldung: Benzin, UN 1203
    var dg: int64 := alloc(EDI_DGD_SIZE);
    i := 0;
    while (i < EDI_DGD_SIZE) { poke8(dg + i, 0); i := i + 1; }
    poke64(dg + EDI_DGD_UNNUMBER,     "1203"c as int64);
    poke64(dg + EDI_DGD_UNLEN,        4);
    poke64(dg + EDI_DGD_IMDGCLASS,    "3"c as int64);
    poke64(dg + EDI_DGD_IMDGLEN,      1);
    poke64(dg + EDI_DGD_PACKINGGROUP, 2);               // II
    poke64(dg + EDI_DGD_EMSCODE,      "F-E,S-E"c as int64);
    poke64(dg + EDI_DGD_EMSLEN,       7);
    poke64(dg + EDI_DGD_QTY,          8000);
    if (EdiUnNumberCheck(peek64(dg + EDI_DGD_UNNUMBER), 4) != 1) { PrintLn("UN-Nummer ungueltig"); return 1; }
    n := EdiIftdgnWrite(hdr, dg, 1, out, 4096);
    PrintLn(Feld(out, n));
    return 0;
}

BGM+310+TRP-2026-0815+9'DTM+137:20260813:102'LOC+87+CNSHA::9'LOC+88+DEMUC::9'NAD+CA+Spedition Nord::9'TDT+1++1'LOC+9+CNSHA::9'LOC+11+DEHAM::9'TDT+2++2'LOC+9+DEHAM::9'LOC+11+DENUE::9'TDT+3++3'LOC+9+DENUE::9'LOC+11+DEMUC::9'CNT+2:3'
Teilstrecken: 3
BGM+214+TRP-2026-0815+9'DTM+137:20260813:102'LOC+87+CNSHA::9'LOC+88+DEMUC::9'NAD+CA+Spedition Nord::9'STS+2'CNT+2:1'
Statuspruefung (0 = ok): 0
Statuspruefung Code 9:    1
IFTFCC-Pruefung (0 = ok): 0
BGM+350+TRP-2026-0815+9'DTM+137:20260813:102'LOC+87+CNSHA::9'LOC+88+DEMUC::9'NAD+CA+Spedition Nord::9'DGS+ADR+1203+3+2+F-E,S-E'CNT+2:1'

Jede Teilstrecke wird als TDT-Segment mit Verkehrsträger (1 See, 2 Bahn, 3 Straße, 4 Luft) und den beiden LOC-Segmenten für Abgang und Ziel geschrieben. Status (STS) und Gefahrgut (DGS) nutzen denselben Kopf-Struct.


Imports

  • std.edi.core
  • std.alloc

Structs

EdiTrnHdr (EDI_TRN_HDR_SIZE = 112 Bytes)

Gemeinsamer Header für alle 8 Nachrichtentypen.

Offset-Konstante Inhalt
EDI_TRN_HDR_BGMQUAL BGM-Qualifier (automatisch gesetzt)
EDI_TRN_HDR_REF / EDI_TRN_HDR_REFLEN Auftrags-/Dokumentreferenz
EDI_TRN_HDR_DATE / EDI_TRN_HDR_DATELEN Datum
EDI_TRN_HDR_DEPARTURE / EDI_TRN_HDR_DEPARTLEN Abgangspunkt (LOC+87, z. B. UN/LOCODE)
EDI_TRN_HDR_ARRIVAL / EDI_TRN_HDR_ARRIVALLEN Bestimmungsort (LOC+88)
EDI_TRN_HDR_CARRIER / EDI_TRN_HDR_CARRIERLEN Spediteur/Carrier (NAD+CA)
EDI_TRN_HDR_BOOKINGREF / EDI_TRN_HDR_BOOKINGLEN Buchungsreferenz (RFF+BN) — Pflicht für IFTFCC
EDI_TRN_HDR_STATUSCODE IFTSTA-Statuscode (1–4)

EdiTrnLeg (EDI_TRN_LEG_SIZE = 40 Bytes)

Ein Beförderungsabschnitt innerhalb eines IFTMIN-Auftrags. IFTMIN kann beliebig viele Legs enthalten — z. B. LKW zum Hafen → Schiff → Bahn zu Empfänger.

Offset-Konstante Inhalt
EDI_TRN_LEG_DEPARTURE / EDI_TRN_LEG_DEPARTLEN Abgangsort des Abschnitts (LOC+9)
EDI_TRN_LEG_ARRIVAL / EDI_TRN_LEG_ARRIVALLEN Ankunftsort des Abschnitts (LOC+11)
EDI_TRN_LEG_MODE Transportmodus: 1=See, 2=Schiene, 3=Straße, 4=Luft

Wire pro Leg: TDT+20+modeLOC+9+departureLOC+11+arrival.

EdiDgd (EDI_DGD_SIZE = 64 Bytes)

Gefahrgutinformation für IFTDGN. Pro Sendung können mehrere DGD-Strukturen vorkommen.

Offset-Konstante Inhalt
EDI_DGD_UNNUMBER / EDI_DGD_UNNUMLEN UN-Nummer (genau 4 Stellen, z. B. „1203“ für Benzin)
EDI_DGD_IMDGCLASS / EDI_DGD_IMDGLEN IMDG-Klasse (z. B. „3“, „8“, „6.1“)
EDI_DGD_PACKINGGROUP Verpackungsgruppe 1–3 (I=höchste, III=niedrigste Gefahr)
EDI_DGD_EMSCODE / EDI_DGD_EMSLEN EMS-Code (Emergency Schedule, z. B. „F-E,S-E“)
EDI_DGD_QTY Menge in der Sendung

Wire: DGS+ADR+unNum+imdgClass+packingGroup+emsCode.


Validierungsfunktionen

Signatur Beschreibung
EdiUnNumberCheck(ptr: int64, len: int64): int64 Prüft UN-Nummer: genau 4 Ziffern (0000–9999). Gibt 1=gültig, 0=ungültig.
EdiIftstaStatusCheck(code: int64): int64 Prüft IFTSTA-Statuscode: 1–4 bekannt → 0; sonst 1 (Warnung, nicht Fehler).
EdiIftfccCheck(hdr: int64): int64 Gibt 2 (Fehler) wenn keine Buchungsreferenz (RFF+BN) vorhanden — Pflichtfeld in IFTFCC.

Funktionen

Einfache Transport-Nachrichten

Write-Funktion Read-Funktion Beschreibung
EdiIftmbcWrite(hdr, out, outMax) EdiIftmbcRead(buf, bufLen, hdr) IFTMIN-Antwort
EdiIftmcsWrite(hdr, out, outMax) EdiIftmcsRead(buf, bufLen, hdr) Vertragsstatus
EdiIftmanWrite(hdr, out, outMax) EdiIftmanRead(buf, bufLen, hdr) Ankunftsankündigung
EdiIfcsumWrite(hdr, out, outMax) EdiIfcsumRead(buf, bufLen, hdr) Frachtabrechnung
EdiIftstaWrite(hdr, out, outMax) EdiIftstaRead(buf, bufLen, hdr) Sendungsstatus
EdiIftfccWrite(hdr, out, outMax) EdiIftfccRead(buf, bufLen, hdr) Frachtkosten

Nachrichten mit Leg-Array (IFTMIN)

Signatur Beschreibung
EdiIftminWrite(hdr: int64, legs: int64, legCount: int64, out: int64, outMax: int64): int64 Schreibt Transportauftrag mit N Beförderungsabschnitten.
EdiIftminRead(buf: int64, bufLen: int64, hdr: int64, legs: int64, maxLegs: int64): int64 Parst IFTMIN; gibt Anzahl der Legs zurück.

Gefahrgutmeldung (IFTDGN)

Signatur Beschreibung
EdiIftdgnWrite(hdr: int64, dgds: int64, dgdCount: int64, out: int64, outMax: int64): int64 Schreibt Gefahrgutmeldung mit N DGD-Einträgen.
EdiIftdgnRead(buf: int64, bufLen: int64, hdr: int64, dgds: int64, maxDgds: int64): int64 Parst IFTDGN; gibt DGD-Anzahl zurück.

Hinweise

  • IFTFCC Buchungsreferenz Pflicht: EdiIftfccCheck gibt Fehler (2) zurück wenn keine Buchungsreferenz (RFF+BN) gesetzt ist. Vor EdiIftfccWrite immer prüfen.
  • UN-Nummer immer 4-stellig: EdiUnNumberCheck verlangt genau 4 Ziffern — also „0012“ statt „12“. Führende Nullen sind Teil der Nummer (z. B. 0004 = Ammoniumnitrat in Lösung).
  • Prüf-Funktionen melden Fehler, nicht Erfolg: EdiIftstaStatusCheck liefert 0 für einen bekannten Code und 1 für einen unbekannten; EdiIftfccCheck 0 bei gesetzter Buchungsreferenz und 2 ohne. Wer auf == 1 als „gültig„ prüft, dreht die Logik um.
  • Gefahrgut-Struct: EDI_DGD_PACKINGGROUP ist eine Zahl (1 = I, 2 = II, 3 = III), UN-Nummer und IMDG-Klasse dagegen Zeiger auf Text. Alles landet in einem DGS+ADR-Segment.
  • Legs nur in IFTMIN: Nur EdiIftminWrite/Read akzeptiert ein Leg-Array. Alle anderen Nachrichten haben genau einen Abgangspunkt und einen Bestimmungsort im Header.

Quelldatei

Unit Datei
std.edi.transport std/edi/transport.lyx

Letzte Aktualisierung: 2026-08-13 — ein durchgehendes, lauffähiges Beispiel für IFTMIN (drei Teilstrecken), IFTSTA und IFTDGN mit echter Ausgabe (lyxc 1.0.17K); Rückgabekonvention der Prüf-Funktionen (0 = ok) richtiggestellt

Codebeispiele geprüft: gegen lyxc 1.2.5C übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die pub fn-Signaturen in aurum/std gehalten, 0 Abweichungen).