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