====== std.edi.shipping ======
Lieferschein und Wareneingangsbestätigung per EDIFACT. DESADV bildet die dreistufige Verpackungshierarchie (Palette → Karton → Artikel) über die EDIFACT-Segmente CPS/PAC/GIN/LIN ab. Jedes Packstück trägt eine SSCC-18-Nummer zur lückenlosen Rückverfolgung.
* **DESADV** (BGM 351) — Dispatch Advice: Lieferschein mit Verpackungsstruktur und SSCC-Nummern
* **RECADV** (BGM 632) — Receiving Advice: Wareneingangsbestätigung mit Soll-/Ist-Mengen und optionalem Abweichungsgrund
SSCC-18-Funktionen:
* ''EdiSsccCheck'' — Prüft Prüfziffer (GS1 Mod-10)
* ''EdiSsccGenerate'' — Berechnet Prüfziffer aus 17-stelliger Basis
import std.edi.shipping;
import std.alloc;
import std.string;
fn main(): int64 {
// 17 Stellen: Erweiterungsziffer + GS1-Basisnummer + laufende Nummer
var sscc: int64 := alloc(19); // 18 Ziffern + NUL
EdiSsccGenerate("34012345000000001"c, sscc);
PrintLn(StrConcat("SSCC: ", sscc as pchar));
PrintLn(StrConcat("Pruefziffer ok: ", IntToStr(EdiSsccCheck(sscc as pchar, 18))));
free(sscc, 19);
return 0;
}
SSCC: 340123450000000017
Pruefziffer ok: 1
----
===== Imports =====
* ''std.edi.core''
* ''std.alloc''
----
===== Konstanten — Pakettypen =====
^ Konstante ^ Wert ^ Bedeutung ^
| ''EDI_PKG_PALLET'' | 1 | Palette (CPS+PAC mit Code 201) |
| ''EDI_PKG_CARTON'' | 2 | Karton (CPS+PAC mit Code CT) |
| ''EDI_PKG_ITEM'' | 3 | Artikel-Ebene (CPS+LIN+QTY) |
----
===== Structs =====
==== EdiPackage (EDI_PACKAGE_SIZE = 56 Bytes) ====
^ Offset-Konstante ^ Inhalt ^
| ''EDI_PACKAGE_SSCC / EDI_PACKAGE_SSCCLEN'' | SSCC-Zeiger (18 Zeichen) und -Länge |
| ''EDI_PACKAGE_TYPE'' | Pakettyp: ''EDI_PKG_PALLET'' / ''EDI_PKG_CARTON'' / ''EDI_PKG_ITEM'' |
| ''EDI_PACKAGE_PARENT'' | Index des übergeordneten Packstücks (0-basiert); ''-1'' wenn keins |
| ''EDI_PACKAGE_GTIN / EDI_PACKAGE_GTINLEN'' | GTIN (nur bei Items) |
| ''EDI_PACKAGE_QTY'' | Menge (nur bei Items) |
**Reihenfolge beim Schreiben**: Erst alle Paletten, dann Kartons, dann Artikel. Der Parent-Index verweist auf den 0-basierten Index im Array.
==== EdiRecadvLine (EDI_RECADV_LINE_SIZE = 56 Bytes) ====
^ Offset-Konstante ^ Inhalt ^
| ''EDI_RECADV_LINE_GTIN / EDI_RECADV_LINE_GTINLEN'' | GTIN-Zeiger und -Länge |
| ''EDI_RECADV_LINE_ORDERED'' | Bestellte Menge (QTY+21) |
| ''EDI_RECADV_LINE_DELIVERED'' | Gelieferte Menge (QTY+12) |
| ''EDI_RECADV_LINE_ACCEPTED'' | Akzeptierte Menge (QTY+192) |
| ''EDI_RECADV_LINE_REASON / EDI_RECADV_LINE_REASONLEN'' | Abweichungsgrund als Freitext (FTX+AAI, optional; 0 wenn keiner) |
----
===== Funktionen =====
==== SSCC-18-Validierung & -Generierung ====
^ Signatur ^ Beschreibung ^
| ''EdiSsccCheck(ptr: int64, len: int64): int64'' | Prüft SSCC-18-Prüfziffer (GS1 Mod-10). Gibt 1=gültig, 0=ungültig. Erwartet exakt 18 Stellen. |
| ''EdiSsccGenerate(base17: int64, out: int64): void'' | Berechnet Prüfziffer aus 17-stelliger Basis-SSCC. Schreibt 18 Stellen + NUL in ''out'' (mind. 19 Bytes). |
==== DESADV ====
^ Signatur ^ Beschreibung ^
| ''EdiDesadvWrite(refNum: int64, date: int64, packages: int64, packCount: int64, out: int64, outMax: int64): int64'' | Schreibt DESADV. Pakete müssen in Hierarchie-Reihenfolge vorliegen (Paletten → Kartons → Items). |
| ''EdiDesadvRead(buf: int64, bufLen: int64, packages: int64, maxPacks: int64): int64'' | Parst DESADV; gibt Paketanzahl zurück oder ''-1'' bei doppelter SSCC. |
==== RECADV ====
^ Signatur ^ Beschreibung ^
| ''EdiRecadvWrite(orderRef: int64, date: int64, lines: int64, lineCount: int64, out: int64, outMax: int64): int64'' | Schreibt RECADV mit Kreuzreferenz auf Bestellnummer (''RFF+ON''). |
| ''EdiRecadvRead(buf: int64, bufLen: int64, lines: int64, maxLines: int64): int64'' | Parst RECADV; gibt Zeilenanzahl zurück. |
----
===== Codebeispiel — DESADV mit Palettenstruktur, dann RECADV =====
import std.edi.shipping;
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 {
// SSCC aus 17 Stellen erzeugen (Prüfziffer haengt die Bibliothek an)
var ssccPal: int64 := alloc(19);
var ssccKar: int64 := alloc(19);
EdiSsccGenerate("34012345000000001"c, ssccPal);
EdiSsccGenerate("34012345000000002"c, ssccKar);
// Hierarchie: Palette -> Karton -> Artikel
var pk: int64 := alloc(3 * EDI_PACKAGE_SIZE);
var i: int64 := 0;
while (i < 3 * EDI_PACKAGE_SIZE) { poke8(pk + i, 0); i := i + 1; }
var p0: int64 := pk;
poke64(p0 + EDI_PACKAGE_SSCC, ssccPal);
poke64(p0 + EDI_PACKAGE_SSCCLEN, 18);
poke64(p0 + EDI_PACKAGE_TYPE, EDI_PKG_PALLET);
poke64(p0 + EDI_PACKAGE_PARENT, 0 - 1);
var p1: int64 := pk + EDI_PACKAGE_SIZE;
poke64(p1 + EDI_PACKAGE_SSCC, ssccKar);
poke64(p1 + EDI_PACKAGE_SSCCLEN, 18);
poke64(p1 + EDI_PACKAGE_TYPE, EDI_PKG_CARTON);
poke64(p1 + EDI_PACKAGE_PARENT, 0); // haengt an Paket 0
var p2: int64 := pk + 2 * EDI_PACKAGE_SIZE;
poke64(p2 + EDI_PACKAGE_TYPE, EDI_PKG_ITEM);
poke64(p2 + EDI_PACKAGE_PARENT, 1); // liegt im Karton
poke64(p2 + EDI_PACKAGE_GTIN, "04012345678901"c as int64);
poke64(p2 + EDI_PACKAGE_GTINLEN, 14);
poke64(p2 + EDI_PACKAGE_QTY, 24);
var out: int64 := alloc(4096);
var n: int64 := EdiDesadvWrite("LS-2026-0815"c, "20260813"c, pk, 3, out, 4096);
PrintLn(Feld(out, n));
var pk2: int64 := alloc(16 * EDI_PACKAGE_SIZE);
var cnt: int64 := EdiDesadvRead(out, n, pk2, 16);
PrintLn(StrConcat("Packstuecke: ", IntToStr(cnt)));
i := 0;
while (i < cnt) {
var p: int64 := pk2 + i * EDI_PACKAGE_SIZE;
PrintLn(StrConcat(StrConcat(" Typ ", IntToStr(peek64(p + EDI_PACKAGE_TYPE))),
StrConcat(" Parent ", IntToStr(peek64(p + EDI_PACKAGE_PARENT)))));
i += 1;
}
// RECADV: 24 bestellt, 24 geliefert, 22 angenommen
var rl: int64 := alloc(EDI_RECADV_LINE_SIZE);
i := 0;
while (i < EDI_RECADV_LINE_SIZE) { poke8(rl + i, 0); i := i + 1; }
poke64(rl + EDI_RECADV_LINE_GTIN, "04012345678901"c as int64);
poke64(rl + EDI_RECADV_LINE_GTINLEN, 14);
poke64(rl + EDI_RECADV_LINE_ORDERED, 24);
poke64(rl + EDI_RECADV_LINE_DELIVERED, 24);
poke64(rl + EDI_RECADV_LINE_ACCEPTED, 22);
poke64(rl + EDI_RECADV_LINE_REASON, "2 Packungen beschaedigt"c as int64);
poke64(rl + EDI_RECADV_LINE_REASONLEN, 23);
n := EdiRecadvWrite("BST-2026-0815"c, "20260814"c, rl, 1, out, 4096);
PrintLn(Feld(out, n));
return 0;
}
BGM+351+LS-2026-0815+9'DTM+137:20260813:102'CPS+1'PAC+1++201'PCI+33E'GIN+BJ+340123450000000017'CPS+2+1'PAC+1++CT'PCI+33E'GIN+BJ+340123450000000024'CPS+3+2'LIN+1++04012345678901:SRV'QTY+12:24'CNT+2:3'
Packstuecke: 3
Typ 1 Parent -1
Typ 2 Parent 0
Typ 3 Parent 1
BGM+632+BST-2026-0815+9'DTM+137:20260814:102'RFF+ON:BST-2026-0815'LIN+1++04012345678901:SRV'QTY+21:24'QTY+12:24'QTY+192:22'FTX+AAI+++2 Packungen beschaedigt'CNT+2:1'
Die Hierarchie steckt in den ''CPS''-Segmenten: ''CPS+1'' ist die Palette (ohne Elternangabe), ''CPS+2+1'' der Karton darunter, ''CPS+3+2'' die Artikelebene. Beim Lesen steht die Elternbeziehung als 0-basierter Index in ''EDI_PACKAGE_PARENT'', ''-1'' bei der obersten Ebene.
Im RECADV stehen drei Mengen nebeneinander: ''QTY+21'' bestellt, ''QTY+12'' geliefert, ''QTY+192'' angenommen — die Differenz begründet das ''FTX''-Segment.
----
===== Hinweise =====
* **SSCC-Duplikatserkennung**: ''EdiDesadvRead'' gibt ''-1'' zurück, wenn dieselbe SSCC-Nummer zweimal im selben Lieferschein steht. Der Rückgabewert ist sonst die Zahl der Packstücke — vor dem Durchlaufen also auf ''< 0'' prüfen.
* **Prüfziffer selbst erzeugen**: ''EdiSsccGenerate'' erwartet genau 17 Stellen und schreibt 18 Ziffern plus Nullbyte (Puffer ≥ 19 Bytes). ''EdiDesadvWrite'' prüft die SSCC **nicht** — wer ungeprüfte Nummern einträgt, verschickt sie auch.
* **Artikelzeilen brauchen keine SSCC**: bei ''EDI_PKG_ITEM'' bleiben SSCC-Zeiger und -Länge 0; dafür sind GTIN und Menge Pflicht.
* **Hierarchie-Reihenfolge**: Beim Schreiben müssen Paletten (''EDI_PKG_PALLET'') vor Kartons und Artikel kommen. Das entspricht der CPS-Reihenfolge in EDIFACT.
* **RECADV Kreuzreferenz**: ''EdiRecadvWrite'' setzt automatisch ''RFF+ON'' mit dem ''orderRef''-Wert. So kann die Gegenseite Wareneingang und Bestellung zuordnen.
----
===== Quelldatei =====
^ Unit ^ Datei ^
| ''std.edi.shipping'' | ''std/edi/shipping.lyx'' |
Letzte Aktualisierung: 2026-08-13 — das defekte SSCC-Beispiel (fehlerhaftes ''StrConcat'') ersetzt, DESADV-Beispiel um den RECADV-Teil erweitert; beide lauffähig, ausgeführt und mit echter Ausgabe belegt (lyxc 1.0.17K)
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).