std.edi.orders

Bestellprozess per EDIFACT: Bestellung, Auftragsbestätigung und Änderungsauftrag. Alle vier NAD-Rollen (Käufer, Lieferant, Lieferadresse, Rechnungsempfänger) werden beim Lesen automatisch extrahiert.

  • ORDERS (BGM 220) — Bestellung (Purchase Order)
  • ORDRSP (BGM 231) — Auftragsbestätigung mit positionsgenauen Status-Codes
  • ORDCHG (BGM 230) — Änderungsauftrag mit laufender Änderungsnummer

import std.edi.orders;
import std.alloc;
import std.string;

// Zero-Copy-Felder sind nicht nullterminiert - terminierte Kopie fuer die Ausgabe.
fn Feld(ptr: int64, len: int64): pchar {
    var b: int64 := alloc(len + 1);
    var i: int64 := 0;
    while (i < len) { poke8(b + i, peek8(ptr + i)); i := i + 1; }
    poke8(b + len, 0);
    return b as pchar;
}

fn main(): int64 {
    // Kopf - Structs immer selbst nullen
    var hdr: int64 := alloc(EDI_ORDER_HDR_SIZE);
    var i: int64 := 0;
    while (i < EDI_ORDER_HDR_SIZE) { poke8(hdr + i, 0); i := i + 1; }
    poke64(hdr + EDI_ORDER_HDR_NUM,        "BST-2026-0815"c as int64);
    poke64(hdr + EDI_ORDER_HDR_NUMLEN,     13);
    poke64(hdr + EDI_ORDER_HDR_DATE,       "20260813"c as int64);
    poke64(hdr + EDI_ORDER_HDR_DATELEN,    8);
    poke64(hdr + EDI_ORDER_HDR_BUYER_GLN,  "4012345000009"c as int64);
    poke64(hdr + EDI_ORDER_HDR_BUYER_GLNL, 13);
    poke64(hdr + EDI_ORDER_HDR_SUP_GLN,    "4098765000004"c as int64);
    poke64(hdr + EDI_ORDER_HDR_SUP_GLNL,   13);

    // Zwei Positionen
    var lines: int64 := alloc(2 * EDI_ORDER_LINE_SIZE);
    i := 0;
    while (i < 2 * EDI_ORDER_LINE_SIZE) { poke8(lines + i, 0); i := i + 1; }
    var l0: int64 := lines;
    poke64(l0 + EDI_ORDER_LINE_GTIN,    "04012345678901"c as int64);
    poke64(l0 + EDI_ORDER_LINE_GTINLEN, 14);
    poke64(l0 + EDI_ORDER_LINE_QTY,     24);
    poke64(l0 + EDI_ORDER_LINE_PRICE,   1999);   // 19,99 EUR
    poke64(l0 + EDI_ORDER_LINE_LINENO,  1);
    var l1: int64 := lines + EDI_ORDER_LINE_SIZE;
    poke64(l1 + EDI_ORDER_LINE_GTIN,    "04012345678918"c as int64);
    poke64(l1 + EDI_ORDER_LINE_GTINLEN, 14);
    poke64(l1 + EDI_ORDER_LINE_QTY,     6);
    poke64(l1 + EDI_ORDER_LINE_PRICE,   4950);   // 49,50 EUR
    poke64(l1 + EDI_ORDER_LINE_LINENO,  2);

    if (EdiOrdersValidate(hdr, lines, 2) != EDI_OK) { PrintLn("ungueltig"); return 1; }

    var out: int64 := alloc(4096);
    var n: int64 := EdiOrdersWrite(hdr, lines, 2, out, 4096);
    PrintLn(Feld(out, n));

    // Und wieder zurueck
    var hdr2: int64 := alloc(EDI_ORDER_HDR_SIZE);
    var lin2: int64 := alloc(8 * EDI_ORDER_LINE_SIZE);
    var cnt: int64 := EdiOrdersRead(out, n, hdr2, lin2, 8);
    PrintLn(StrConcat("Positionen: ", IntToStr(cnt)));
    PrintLn(StrConcat("Bestellnr:  ", Feld(peek64(hdr2 + EDI_ORDER_HDR_NUM), peek64(hdr2 + EDI_ORDER_HDR_NUMLEN))));
    PrintLn(StrConcat("Summe/100:  ", IntToStr(peek64(hdr2 + EDI_ORDER_HDR_TOTAL))));
    return 0;
}

BGM+220+BST-2026-0815+9'DTM+137:20260813:102'NAD+BY+4012345000009::9'NAD+SU+4098765000004::9'LIN+1++04012345678901:SRV'QTY+21:24'PRI+AAA:19.99:CP'LIN+2++04012345678918:SRV'QTY+21:6'PRI+AAA:49.50:CP'UNS+S'MOA+77:776.76'CNT+2:2'
Positionen: 2
Bestellnr:  BST-2026-0815
Summe/100:  77676

EdiOrdersWrite erzeugt nur den Nachrichtenrumpf. Umschlag (UNA/UNB/UNH … UNT/UNZ) kommt aus std.edi.core. Den Gesamtbetrag (MOA+77) rechnet die Funktion selbst aus den Positionen aus — ihn im Kopf zu setzen ist nur für EdiOrdersValidate nötig.


Imports

  • std.edi.core
  • std.alloc

Structs

EdiOrderLine (EDI_ORDER_LINE_SIZE = 80 Bytes)

Offset-Konstante Inhalt
EDI_ORDER_LINE_GTIN / EDI_ORDER_LINE_GTINLEN GTIN-Zeiger und -Länge
EDI_ORDER_LINE_QTY Bestellmenge
EDI_ORDER_LINE_UNIT / EDI_ORDER_LINE_UNITLEN Mengeneinheit (optional)
EDI_ORDER_LINE_PRICE Einzelpreis × 100 (Festkomma)
EDI_ORDER_LINE_TAXRATE Steuersatz × 100 (z. B. 1900 = 19,00 %)
EDI_ORDER_LINE_DATE Zeiger auf Lieferdatum „YYYYMMDD“ (0 = kein Wunschtermin)
EDI_ORDER_LINE_STATUS Position-Status: 0=normal, 1=bestätigt, 5=geändert, 7=abgelehnt
EDI_ORDER_LINE_LINENO Zeilennummer (1-basiert)

EdiOrderHdr (EDI_ORDER_HDR_SIZE = 112 Bytes)

Offset-Konstante Inhalt
EDI_ORDER_HDR_NUM / EDI_ORDER_HDR_NUMLEN Bestellnummer
EDI_ORDER_HDR_DATE / EDI_ORDER_HDR_DATELEN Bestelldatum
EDI_ORDER_HDR_BUYER_GLN / EDI_ORDER_HDR_BUYER_GLNL GLN Käufer (NAD+BY)
EDI_ORDER_HDR_SUP_GLN / EDI_ORDER_HDR_SUP_GLNL GLN Lieferant (NAD+SU)
EDI_ORDER_HDR_DELIV_GLN / EDI_ORDER_HDR_DELIV_GLNL GLN Lieferadresse (NAD+DP)
EDI_ORDER_HDR_INV_GLN / EDI_ORDER_HDR_INV_GLNL GLN Rechnungsempfänger (NAD+IV)
EDI_ORDER_HDR_TOTAL Gesamtbetrag × 100 (MOA+77)
EDI_ORDER_HDR_CHANGENO Änderungsnummer (ORDCHG: muss pro Änderung erhöht werden)

Funktionen

ORDERS

Signatur Beschreibung
EdiOrdersWrite(hdr: int64, lines: int64, lineCount: int64, out: int64, outMax: int64): int64 Schreibt ORDERS. Gibt -1 wenn Bestellnummer fehlt.
EdiOrdersRead(buf: int64, bufLen: int64, hdr: int64, lines: int64, maxLines: int64): int64 Parst ORDERS; befüllt hdr und lines. Gibt Zeilenanzahl zurück. Alle 4 NAD-Rollen werden extrahiert.
EdiOrdersValidate(hdr: int64, lines: int64, lineCount: int64): int64 Vergleicht die Summe aller Positionen (qty × price, in Cent) mit EDI_ORDER_HDR_TOTAL. Toleranz 1 Cent. 0 (= EDI_OK) bei Übereinstimmung, 1 bei Abweichung. Ist TOTAL 0, gibt die Funktion ohne Prüfung 0 zurück.

ORDRSP — Auftragsbestätigung

Signatur Beschreibung
EdiOrdrspWrite(orderRef: int64, confirmNum: int64, lines: int64, lineCount: int64, out: int64, outMax: int64): int64 Schreibt ORDRSP mit Positionsstatus (STATUS-Feld der Zeilen: 1=bestätigt, 5=geändert, 7=abgelehnt)
EdiOrdrspRead(buf: int64, bufLen: int64, hdr: int64, lines: int64, maxLines: int64): int64 Parst ORDRSP; gibt Zeilenanzahl zurück

ORDCHG — Änderungsauftrag

Signatur Beschreibung
EdiOrdchgWrite(orderRef: int64, changeNo: int64, lines: int64, lineCount: int64, out: int64, outMax: int64): int64 Schreibt ORDCHG. changeNo muss mit jeder Änderung erhöht werden (EDIFACT-Pflicht).
EdiOrdchgRead(buf: int64, bufLen: int64, hdr: int64, lines: int64, maxLines: int64): int64 Parst ORDCHG; befüllt hdr.EDI_ORDER_HDR_CHANGENO

Codebeispiel — Auftragsbestätigung schreiben und auswerten

import std.edi.orders;
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 lines: int64 := alloc(2 * EDI_ORDER_LINE_SIZE);
    var i: int64 := 0;
    while (i < 2 * EDI_ORDER_LINE_SIZE) { poke8(lines + i, 0); i := i + 1; }

    // Position 1 bestaetigt, Position 2 abgelehnt
    poke64(lines + EDI_ORDER_LINE_GTIN,    "04012345678901"c as int64);
    poke64(lines + EDI_ORDER_LINE_GTINLEN, 14);
    poke64(lines + EDI_ORDER_LINE_QTY,     24);
    poke64(lines + EDI_ORDER_LINE_LINENO,  1);
    poke64(lines + EDI_ORDER_LINE_STATUS,  1);
    var l1: int64 := lines + EDI_ORDER_LINE_SIZE;
    poke64(l1 + EDI_ORDER_LINE_GTIN,    "04012345678918"c as int64);
    poke64(l1 + EDI_ORDER_LINE_GTINLEN, 14);
    poke64(l1 + EDI_ORDER_LINE_QTY,     0);
    poke64(l1 + EDI_ORDER_LINE_LINENO,  2);
    poke64(l1 + EDI_ORDER_LINE_STATUS,  7);

    // orderRef und confirmNum sind nullterminierte Strings, keine Zahlen
    var out: int64 := alloc(4096);
    var n: int64 := EdiOrdrspWrite("BST-2026-0815"c, "AB-9001"c, lines, 2, out, 4096);
    PrintLn(Feld(out, n));

    var hdr2: int64 := alloc(EDI_ORDER_HDR_SIZE);
    var lin2: int64 := alloc(8 * EDI_ORDER_LINE_SIZE);
    var cnt: int64 := EdiOrdrspRead(out, n, hdr2, lin2, 8);
    i := 0;
    while (i < cnt) {
        var l: int64 := lin2 + i * EDI_ORDER_LINE_SIZE;
        var st: int64 := peek64(l + EDI_ORDER_LINE_STATUS);
        if (st == 1) { PrintLn(StrConcat("bestaetigt: Position ", IntToStr(peek64(l + EDI_ORDER_LINE_LINENO)))); }
        if (st == 7) { PrintLn(StrConcat("abgelehnt:  Position ", IntToStr(peek64(l + EDI_ORDER_LINE_LINENO)))); }
        i += 1;
    }
    return 0;
}

BGM+231+AB-9001+9'RFF+ON:BST-2026-0815'LIN+1+1+04012345678901:SRV'QTY+21:24'LIN+2+7+04012345678918:SRV'QTY+21:0'CNT+2:2'
bestaetigt: Position 1
abgelehnt:  Position 2


Hinweise

  • Änderungsnummer ORDCHG: EDI_ORDER_HDR_CHANGENO muss mit jeder neuen ORDCHG inkrementiert werden. Die Gegenseite erkennt damit, ob sie die aktuellste Änderung sieht.
  • NAD-Rollen: EdiOrdersRead extrahiert alle vier Rollen. Nicht vorhandene Rollen haben Zeiger 0 und Länge 0.
  • Gesamtbetrag-Validierung: EdiOrdersValidate erlaubt 1 Cent Rundungsabweichung. Ohne gesetzten EDI_ORDER_HDR_TOTAL prüft sie nichts — wer validieren will, muss den erwarteten Betrag vorher eintragen.
  • Der Kopf-Gesamtbetrag wird beim Schreiben überschrieben: EdiOrdersWrite rechnet MOA+77 selbst aus den Positionen aus.
  • Strings statt Zahlen bei ORDRSP/ORDCHG: orderRef und confirmNum sind Zeiger auf nullterminierten Text ("AB-9001"c as int64); nur changeNo bei EdiOrdchgWrite ist eine echte Zahl.
  • Structs selbst nullen. EdiOrdersWrite liest jedes Feld; nicht initialisierter Speicher erzeugt Zufallszeiger. EdiOrdersRead nullt den Kopf dagegen selbst.
  • Preise und Beträge sind ×10077676 bedeutet 776,76 €.

Quelldatei

Unit Datei
std.edi.orders std/edi/orders.lyx

Letzte Aktualisierung: 2026-08-13 — beide Beispiele lauffähig gemacht, ausgeführt und um die echten Ausgaben ergänzt (lyxc 1.0.17K); Semantik von EdiOrdersValidate (TOTAL = 0 prüft nichts) und die Zeiger-Parameter von ORDRSP/ORDCHG klargestellt

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).