====== std.edi.customs ======
Zoll-Nachrichten per EDIFACT für den grenzüberschreitenden Warenverkehr. Alle vier Nachrichtentypen teilen denselben Header (EDI_CUS_HDR) mit Absender, Empfänger, Herkunfts-/Zielort, Zollbehörde-Referenz und Zollwert.
* **CUSCAR** (BGM 85) — Customs Cargo Report: Carrier meldet Ladung bei Zollbehörde
* **CUSDEC** (BGM 960) — Customs Declaration: Anmeldung durch Zollanmelder
* **CUSEXP** (BGM 962) — Customs Express: Express-Sendungsmanifest (Kurier)
* **CUSRSP** (BGM 961) — Customs Response: Antwort der Zollbehörde
CUSRSP-Statuscodes:
^ Konstante ^ Wert ^ Bedeutung ^
| ''EDI_CUSRSP_ACCEPTED'' | 1 | Anmeldung akzeptiert |
| ''EDI_CUSRSP_REJECTED'' | 2 | Anmeldung abgelehnt |
| ''EDI_CUSRSP_QUERIED'' | 3 | Rückfrage / weitere Informationen benötigt |
| ''EDI_CUSRSP_RELEASED'' | 4 | Waren freigegeben |
import std.edi.customs;
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_CUS_HDR_SIZE);
var i: int64 := 0;
while (i < EDI_CUS_HDR_SIZE) { poke8(hdr + i, 0); i := i + 1; }
poke64(hdr + EDI_CUS_HDR_REF, "ZOLL-2026-0042"c as int64);
poke64(hdr + EDI_CUS_HDR_REFLEN, 14);
poke64(hdr + EDI_CUS_HDR_DATE, "20260813"c as int64);
poke64(hdr + EDI_CUS_HDR_DATELEN, 8);
poke64(hdr + EDI_CUS_HDR_ORIGIN, "CNSHA"c as int64); // Shanghai
poke64(hdr + EDI_CUS_HDR_ORIGLEN, 5);
poke64(hdr + EDI_CUS_HDR_DEST, "DEHAM"c as int64); // Hamburg
poke64(hdr + EDI_CUS_HDR_DESTLEN, 5);
poke64(hdr + EDI_CUS_HDR_DECLARANT, "Muster Handel GmbH"c as int64);
poke64(hdr + EDI_CUS_HDR_DECLLEN, 18);
poke64(hdr + EDI_CUS_HDR_CARRIER, "Reederei Nord"c as int64);
poke64(hdr + EDI_CUS_HDR_CARRLEN, 13);
poke64(hdr + EDI_CUS_HDR_CUSTVALUE, 1250000); // 12.500,00 EUR
poke64(hdr + EDI_CUS_HDR_CURRENCY, "EUR"c as int64);
poke64(hdr + EDI_CUS_HDR_CURLEN, 3);
poke64(hdr + EDI_CUS_HDR_PROCCODE, 4000); // Ueberfuehrung freier Verkehr
var items: int64 := alloc(2 * EDI_CUS_ITEM_SIZE);
i := 0;
while (i < 2 * EDI_CUS_ITEM_SIZE) { poke8(items + i, 0); i := i + 1; }
poke64(items + EDI_CUS_ITEM_DESC, "Kaffee geroestet"c as int64);
poke64(items + EDI_CUS_ITEM_DESCLEN, 16);
poke64(items + EDI_CUS_ITEM_QTY, 500);
poke64(items + EDI_CUS_ITEM_VALUE, 900000);
poke64(items + EDI_CUS_ITEM_HSCODE, "09012100"c as int64);
poke64(items + EDI_CUS_ITEM_HSCODELEN, 8);
var it1: int64 := items + EDI_CUS_ITEM_SIZE;
poke64(it1 + EDI_CUS_ITEM_DESC, "Teemischung"c as int64);
poke64(it1 + EDI_CUS_ITEM_DESCLEN, 11);
poke64(it1 + EDI_CUS_ITEM_QTY, 200);
poke64(it1 + EDI_CUS_ITEM_VALUE, 350000);
poke64(it1 + EDI_CUS_ITEM_HSCODE, "09024000"c as int64);
poke64(it1 + EDI_CUS_ITEM_HSCODELEN, 8);
var out: int64 := alloc(4096);
var n: int64 := EdiCusdecWrite(hdr, items, 2, out, 4096);
PrintLn(Feld(out, n));
var hdr2: int64 := alloc(EDI_CUS_HDR_SIZE);
var it2: int64 := alloc(8 * EDI_CUS_ITEM_SIZE);
var cnt: int64 := EdiCusdecRead(out, n, hdr2, it2, 8);
PrintLn(StrConcat(StrConcat("Positionen: ", IntToStr(cnt)),
StrConcat(" Zollwert/100: ", IntToStr(peek64(hdr2 + EDI_CUS_HDR_CUSTVALUE)))));
// Behoerdenantwort: Ware freigegeben
var rsp: int64 := alloc(EDI_CUS_HDR_SIZE);
i := 0;
while (i < EDI_CUS_HDR_SIZE) { poke8(rsp + i, 0); i := i + 1; }
poke64(rsp + EDI_CUS_HDR_REF, "RSP-2026-0042"c as int64);
poke64(rsp + EDI_CUS_HDR_REFLEN, 13);
poke64(rsp + EDI_CUS_HDR_DECLREF, "ZOLL-2026-0042"c as int64);
poke64(rsp + EDI_CUS_HDR_DECLREFLEN, 14);
poke64(rsp + EDI_CUS_HDR_RSPCODE, EDI_CUSRSP_RELEASED);
n := EdiCusrspWrite(rsp, out, 4096);
PrintLn(Feld(out, n));
var rsp2: int64 := alloc(EDI_CUS_HDR_SIZE);
EdiCusrspRead(out, n, rsp2);
var code: int64 := peek64(rsp2 + EDI_CUS_HDR_RSPCODE);
if (code == EDI_CUSRSP_RELEASED) { PrintLn("Ware freigegeben"); }
if (code == EDI_CUSRSP_REJECTED) { PrintLn("Anmeldung abgelehnt"); }
return 0;
}
BGM+960+ZOLL-2026-0042+9'DTM+137:20260813:102'LOC+87+CNSHA::9'LOC+88+DEHAM::9'NAD+DT+Muster Handel GmbH::9'NAD+CA+Reederei Nord::9'CUX+2:EUR:4'MOA+126:12500.00'GIS+4000'LIN+1+Kaffee geroestet'QTY+1:500'MOA+66:9000.00'RFF+HS:09012100'LIN+2+Teemischung'QTY+1:200'MOA+66:3500.00'RFF+HS:09024000'CNT+2:2'
Positionen: 2 Zollwert/100: 1250000
BGM+961+RSP-2026-0042+9'RFF+ADE:ZOLL-2026-0042'STS+4'CNT+2:1'
Ware freigegeben
''LOC+87'' ist der Abgangs-, ''LOC+88'' der Bestimmungsort (UN/LOCODE), ''GIS'' trägt den Zollverfahrenscode, ''MOA+126'' den Gesamt- und ''MOA+66'' den Positionszollwert. Die Behördenantwort besteht aus ''RFF+ADE'' (Bezug zur Anmeldung) und ''STS'' mit dem Statuscode.
----
===== Imports =====
* ''std.edi.core''
* ''std.alloc''
----
===== Structs =====
==== EdiCusHdr (EDI_CUS_HDR_SIZE = 160 Bytes) ====
^ Offset-Konstante ^ Inhalt ^
| ''EDI_CUS_HDR_BGMQUAL'' | BGM-Qualifier (''EDI_CUS_BGM_*'') |
| ''EDI_CUS_HDR_REF / EDI_CUS_HDR_REFLEN'' | Referenz/Dokumentnummer |
| ''EDI_CUS_HDR_DATE / EDI_CUS_HDR_DATELEN'' | Datum |
| ''EDI_CUS_HDR_ORIGIN / EDI_CUS_HDR_ORIGLEN'' | Herkunftsland (LOC+87, z. B. "CN") |
| ''EDI_CUS_HDR_DEST / EDI_CUS_HDR_DESTLEN'' | Bestimmungsland (LOC+88, z. B. "DE") |
| ''EDI_CUS_HDR_DECLARANT / EDI_CUS_HDR_DECLLEN'' | Zollanmelder (NAD+DT) |
| ''EDI_CUS_HDR_CARRIER / EDI_CUS_HDR_CARRLEN'' | Beförderer (NAD+CA) |
| ''EDI_CUS_HDR_CUSTVALUE'' | Zollwert × 100 (MOA+126) |
| ''EDI_CUS_HDR_CURRENCY / EDI_CUS_HDR_CURLEN'' | Währungscode |
| ''EDI_CUS_HDR_DECLREF / EDI_CUS_HDR_DECLREFLEN'' | Zollanmeldungsnummer (RFF+ADE) |
| ''EDI_CUS_HDR_RSPCODE'' | CUSRSP-Statuscode (1–4) |
| ''EDI_CUS_HDR_PROCCODE'' | Zollverfahrenscode |
==== EdiCusItem (EDI_CUS_ITEM_SIZE = 48 Bytes) ====
^ Offset-Konstante ^ Inhalt ^
| ''EDI_CUS_ITEM_DESC / EDI_CUS_ITEM_DESCLEN'' | Warenbeschreibung (LIN) |
| ''EDI_CUS_ITEM_QTY'' | Menge |
| ''EDI_CUS_ITEM_VALUE'' | Positionswert × 100 (MOA+66) |
| ''EDI_CUS_ITEM_HSCODE / EDI_CUS_ITEM_HSCODELEN'' | HS-Zolltarifnummer (RFF+HS) |
----
===== Funktionen =====
^ Write-Funktion ^ Read-Funktion ^ Beschreibung ^
| ''EdiCuscarWrite(hdr, items, itemCount, out, outMax)'' | ''EdiCuscarRead(buf, bufLen, hdr, items, maxItems)'' | Cargo Report |
| ''EdiCusdecWrite(hdr, items, itemCount, out, outMax)'' | ''EdiCusdecRead(buf, bufLen, hdr, items, maxItems)'' | Zollanmeldung |
| ''EdiCusexpWrite(hdr, items, itemCount, out, outMax)'' | ''EdiCusexpRead(buf, bufLen, hdr, items, maxItems)'' | Express-Manifest |
| ''EdiCusrspWrite(hdr, out, outMax)'' | ''EdiCusrspRead(buf, bufLen, hdr)'' | Zollantwort (kein Item-Array) |
Alle Write-Funktionen setzen automatisch den BGM-Qualifier. Read-Funktionen geben die Anzahl der Items zurück (für CUSRSP: 1=ok, 0=Fehler).
----
===== Hinweise =====
* **HS-Code (RFF+HS)**: Die 6- bis 10-stellige HS-Zolltarifnummer identifiziert die Warengruppe international. Korrekte HS-Codes sind Voraussetzung für den automatisierten Zollabschluss.
* **Zollwert (MOA+126)**: Muss in der Währung aus CUX angegeben werden. Festkomma × 100.
* **CUSRSP ohne Items**: ''EdiCusrspWrite/Read'' hat kein Item-Array — die Antwort bezieht sich immer auf die gesamte Anmeldung. Pflichtfelder sind ''EDI_CUS_HDR_DECLREF'' (Bezug zur Anmeldung) und ''EDI_CUS_HDR_RSPCODE''.
* **Statuscodes der Antwort**: ''EDI_CUSRSP_ACCEPTED'' (1) angenommen, ''EDI_CUSRSP_REJECTED'' (2) abgelehnt, ''EDI_CUSRSP_QUERIED'' (3) Rückfrage, ''EDI_CUSRSP_RELEASED'' (4) Ware freigegeben.
* **BGM-Qualifier setzt die Bibliothek selbst**: ''EdiCuscarWrite'' schreibt 85, ''EdiCusdecWrite'' 960, ''EdiCusexpWrite'' 962, ''EdiCusrspWrite'' 961 — ein selbst gesetzter ''EDI_CUS_HDR_BGMQUAL'' wird überschrieben. Alle vier Nachrichten teilen sich denselben Kopf-Struct.
* **Alle vier Nachrichten nutzen dieselben Item-Structs**; für CUSCAR (Frachtanmeldung) ist die Warenbeschreibung Pflicht, für CUSDEC zusätzlich der HS-Code.
----
===== Quelldatei =====
^ Unit ^ Datei ^
| ''std.edi.customs'' | ''std/edi/customs.lyx'' |
Letzte Aktualisierung: 2026-08-13 — ein durchgehendes, lauffähiges Beispiel (Zollanmeldung → Behördenantwort) mit echter Ausgabe (lyxc 1.0.17K); Statuscodes und das automatische Setzen des BGM-Qualifiers dokumentiert
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).