std.edi.catalog

Stammdaten-Austausch per EDIFACT: Artikelkataloge mit Preisen und Gültigkeitszeiträumen (PRICAT) sowie Partnerdaten mit GLN-Adressen (PARTIN). GS1-Validierungsfunktionen für GTIN und GLN sind in dieser Unit enthalten.

  • PRICAT — Price/Sales Catalogue: GTINs, Brutto-/Nettopreise, Mengeneinheiten, Gültigkeitszeiträume
  • PARTIN — Party Information: GLN-basierte Adressen und Kontaktdaten

GS1-Validierungen:

Funktion Unterstützte Längen Algorithmus
EdiGtinCheck 8, 12, 13, 14 Stellen GS1 Mod-10 (Prüfziffer)
EdiGlnCheck 13 Stellen GS1 Mod-10

Achtung: EdiPricatWrite validiert GTINs nicht — das liegt in der Verantwortung des Callers.

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

    var a: int64 := items;
    poke64(a + EDI_PRICAT_GTIN,        "04012345678901"c as int64);
    poke64(a + EDI_PRICAT_GTINLEN,     14);
    poke64(a + EDI_PRICAT_DESC,        "Kaffee gemahlen 500g"c as int64);
    poke64(a + EDI_PRICAT_DESCLEN,     20);
    poke64(a + EDI_PRICAT_GROSSPRICE,  1999);
    poke64(a + EDI_PRICAT_NETPRICE,    1799);
    poke64(a + EDI_PRICAT_CURRENCY,    "EUR"c as int64);
    poke64(a + EDI_PRICAT_CURRENCYLEN, 3);
    poke64(a + EDI_PRICAT_VALIDFROM,   "20260901"c as int64);
    poke64(a + EDI_PRICAT_VALIDTO,     "20261231"c as int64);

    var b: int64 := items + EDI_PRICAT_ITEM_SIZE;
    poke64(b + EDI_PRICAT_GTIN,        "04012345678918"c as int64);
    poke64(b + EDI_PRICAT_GTINLEN,     14);
    poke64(b + EDI_PRICAT_DESC,        "Espressobohnen 1kg"c as int64);
    poke64(b + EDI_PRICAT_DESCLEN,     18);
    poke64(b + EDI_PRICAT_GROSSPRICE,  4950);
    poke64(b + EDI_PRICAT_NETPRICE,    4450);
    poke64(b + EDI_PRICAT_CURRENCY,    "EUR"c as int64);
    poke64(b + EDI_PRICAT_CURRENCYLEN, 3);

    // GTIN vor dem Schreiben selbst pruefen - PRICAT tut es nicht
    if (EdiGtinCheck(peek64(a + EDI_PRICAT_GTIN) as pchar, 14) != 1) { PrintLn("GTIN ungueltig"); return 1; }

    var out: int64 := alloc(4096);
    var n: int64 := EdiPricatWrite(items, 2, out, 4096);
    PrintLn(Feld(out, n));

    var it2: int64 := alloc(8 * EDI_PRICAT_ITEM_SIZE);
    var cnt: int64 := EdiPricatRead(out, n, it2, 8);
    PrintLn(StrConcat("Artikel: ", IntToStr(cnt)));
    i := 0;
    while (i < cnt) {
        var it: int64 := it2 + i * EDI_PRICAT_ITEM_SIZE;
        PrintLn(StrConcat(StrConcat("  ", Feld(peek64(it + EDI_PRICAT_GTIN), peek64(it + EDI_PRICAT_GTINLEN))),
                StrConcat("  netto/100: ", IntToStr(peek64(it + EDI_PRICAT_NETPRICE)))));
        i += 1;
    }

    // PARTIN: Stammdaten eines Partners
    var party: int64 := alloc(EDI_PARTY_SIZE);
    i := 0;
    while (i < EDI_PARTY_SIZE) { poke8(party + i, 0); i := i + 1; }
    poke64(party + EDI_PARTY_GLN,       "4012345000009"c as int64);
    poke64(party + EDI_PARTY_GLNLEN,    13);
    poke64(party + EDI_PARTY_NAME,      "Muster Handel GmbH"c as int64);
    poke64(party + EDI_PARTY_NAMELEN,   18);
    poke64(party + EDI_PARTY_STREET,    "Hafenstrasse 12"c as int64);
    poke64(party + EDI_PARTY_STREETL,   15);
    poke64(party + EDI_PARTY_CITY,      "Hamburg"c as int64);
    poke64(party + EDI_PARTY_CITYL,     7);
    poke64(party + EDI_PARTY_POSTCODE,  "20457"c as int64);
    poke64(party + EDI_PARTY_POSTCODEL, 5);
    poke64(party + EDI_PARTY_COUNTRY,   "DE"c as int64);
    poke64(party + EDI_PARTY_COUNTRYL,  2);
    poke64(party + EDI_PARTY_ROLE,      "BY"c as int64);
    poke64(party + EDI_PARTY_ROLEL,     2);
    n := EdiPartinWrite(party, out, 4096);
    PrintLn(Feld(out, n));
    return 0;
}

BGM+9+PRICAT+9'LIN+1++04012345678901:SRV'IMD+F++:::Kaffee gemahlen 500g'PRI+AAB:19.99:CP'PRI+AAA:17.99:CP'DTM+194:20260901:102'DTM+206:20261231:102'LIN+2++04012345678918:SRV'IMD+F++:::Espressobohnen 1kg'PRI+AAB:49.50:CP'PRI+AAA:44.50:CP'CNT+2:2'
Artikel: 2
  04012345678901  netto/100: 1799
  04012345678918  netto/100: 4450
BGM+349++9'NAD+BY+4012345000009::9+Muster Handel GmbH+Hafenstrasse 12+Hamburg+20457+DE'

PRI+AAB trägt den Brutto-, PRI+AAA den Nettopreis; DTM+194/DTM+206 sind Beginn und Ende der Preisgültigkeit. Fehlt ein Gültigkeitsdatum, entfällt das jeweilige DTM-Segment (siehe zweiter Artikel).


Imports

  • std.edi.core
  • std.alloc

Structs

EdiPricatItem (EDI_PRICAT_ITEM_SIZE = 96 Bytes)

Offset-Konstante Inhalt
EDI_PRICAT_GTIN / EDI_PRICAT_GTINLEN GTIN-Zeiger und -Länge
EDI_PRICAT_DESC / EDI_PRICAT_DESCLEN Artikelbeschreibung
EDI_PRICAT_GROSSPRICE Bruttopreis × 100 (z. B. 299 = 2,99 €)
EDI_PRICAT_NETPRICE Nettopreis × 100
EDI_PRICAT_CURRENCY / EDI_PRICAT_CURRENCYLEN Währungscode (z. B. „EUR“)
EDI_PRICAT_UNIT / EDI_PRICAT_UNITLEN Mengeneinheit (z. B. „PCE“, optional)
EDI_PRICAT_VALIDFROM Zeiger auf Gültigkeitsbeginn „YYYYMMDD“ (0 = keins)
EDI_PRICAT_VALIDTO Zeiger auf Gültigkeitsende „YYYYMMDD“ (0 = keins)

EdiParty (EDI_PARTY_SIZE = 112 Bytes)

Offset-Konstante Inhalt
EDI_PARTY_GLN / EDI_PARTY_GLNLEN GLN-Zeiger und -Länge
EDI_PARTY_NAME / EDI_PARTY_NAMELEN Firmenname
EDI_PARTY_STREET / EDI_PARTY_STREETL Straße + Hausnummer
EDI_PARTY_CITY / EDI_PARTY_CITYL Ort
EDI_PARTY_POSTCODE / EDI_PARTY_POSTCODEL Postleitzahl
EDI_PARTY_COUNTRY / EDI_PARTY_COUNTRYL Ländercode (z. B. „DE“)
EDI_PARTY_ROLE / EDI_PARTY_ROLEL Parteirolle (z. B. „SU“, „BY“)

EdiProact (EDI_PROACT_SIZE = 40 Bytes)

Aktivitätsdaten (PROACT) für Warengruppen-Berichte.

Offset-Konstante Inhalt
EDI_PROACT_GTIN / EDI_PROACT_GTINLEN GTIN-Zeiger und -Länge
EDI_PROACT_QTY Menge × 1000 (3 Dezimalstellen)
EDI_PROACT_DATE Zeiger auf Datum „YYYYMMDD“
EDI_PROACT_TYPE Aktivitätstyp: 1=Verkauf, 2=Rückgabe, 3=Transfer

Funktionen

GS1-Validierung

Signatur Beschreibung
EdiGtinCheck(ptr: pchar, len: int64): int64 Prüft GTIN-Prüfziffer (Mod-10). Gibt 1=gültig, 0=ungültig. Unterstützt Längen 8, 12, 13, 14.
EdiGlnCheck(ptr: int64, len: int64): int64 Prüft GLN-Prüfziffer (Mod-10). Gibt 1=gültig, 0=ungültig. Erwartet exakt 13 Stellen.

PRICAT

Signatur Beschreibung
EdiPricatWrite(items: int64, count: int64, out: int64, outMax: int64): int64 Schreibt PRICAT. GTINs werden nicht validiert (Caller-Verantwortung).
EdiPricatRead(buf: int64, bufLen: int64, items: int64, maxItems: int64): int64 Parst PRICAT; gibt Artikelanzahl zurück. Zero-Copy: Zeiger in items zeigen in buf.

PARTIN

Signatur Beschreibung
EdiPartinWrite(party: int64, out: int64, outMax: int64): int64 Schreibt PARTIN (eine Partei)
EdiPartinRead(buf: int64, bufLen: int64, party: int64): int64 Parst PARTIN; gibt EDI_OK oder Fehlercode

Codebeispiel — eingehenden Katalog prüfen

import std.edi.catalog;
import std.alloc;
import std.string;

fn main(): int64 {
    // Zweite GTIN traegt absichtlich eine falsche Pruefziffer
    var msg: pchar := "BGM+9+PRICAT+9'LIN+1++04012345678901:SRV'PRI+AAA:17.99:CP'LIN+2++04012345678911:SRV'PRI+AAA:44.50:CP'CNT+2:2'"c;

    var items: int64 := alloc(64 * EDI_PRICAT_ITEM_SIZE);
    var count: int64 := EdiPricatRead(msg as int64, StrLen(msg), items, 64);
    PrintLn(StrConcat("Positionen: ", IntToStr(count)));

    var i: int64 := 0;
    while (i < count) {
        var item: int64 := items + i * EDI_PRICAT_ITEM_SIZE;
        var gptr: int64 := peek64(item + EDI_PRICAT_GTIN);
        var glen: int64 := peek64(item + EDI_PRICAT_GTINLEN);
        if (EdiGtinCheck(gptr as pchar, glen) == 0) {
            PrintLn(StrConcat("Ungueltige GTIN in Position ", IntToStr(i + 1)));
        }
        i := i + 1;
    }
    free(items, 64 * EDI_PRICAT_ITEM_SIZE);
    return 0;
}

Positionen: 2
Ungueltige GTIN in Position 2


Hinweise

  • Keine Prüfung beim Schreiben: Weder EdiPricatWrite noch EdiPartinWrite prüfen GTIN oder GLN. Wer sich auf saubere Stammdaten verlässt, ruft EdiGtinCheck/EdiGlnCheck selbst auf — beim Erzeugen wie beim Einlesen.
  • Preise sind ×100: 1799 bedeutet 17,99 €. EDI_PRICAT_GROSSPRICE ist der Listen-, EDI_PRICAT_NETPRICE der Nettopreis.
  • Gültigkeitsdaten sind Zeiger auf YYYYMMDD (8 Zeichen, ohne Längenfeld) oder 0.
  • PARTIN schreibt eine Partei je Aufruf: EdiPartinWrite erzeugt BGM+349 und ein NAD-Segment mit der Rolle aus EDI_PARTY_ROLE (BY Käufer, SU Lieferant, DP Lieferstelle, IV Rechnungsempfänger).
  • Structs vor dem Befüllen nullenEdiPricatWrite liest jedes Feld, auch die optionalen.

Quelldatei

Unit Datei
std.edi.catalog std/edi/catalog.lyx

Letzte Aktualisierung: 2026-08-13 — beide Beispiele lauffähig gemacht und ausgeführt (lyxc 1.0.17K), PARTIN-Beispiel und Hinweisabschnitt ergänzt

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