====== std.edi.payment ======
Zahlungs- und Bankdaten per EDIFACT. Alle 13 Nachrichtentypen teilen dieselbe Header-Struktur (EDI_PAY_HDR). Spezifische Validierungen schützen vor häufigen Fehlern: fehlendes Rechnungsreferenz in REMADV (Warnung), fehlendes Mandat in DIRDEB (Fehler), fehlendes Transaktionskennzeichen in FINCAN (Fehler). Alle Beträge werden als ''int64 × 100'' gespeichert (Festkomma).
IBAN-Validierung (MOD-97) und BIC-Format-Prüfung (8 oder 11 Zeichen) sind direkt in dieser Unit enthalten.
| **REMADV** (481) | Zahlungsavis — Zuordnung von Zahlung zu Rechnungen |
| **PAYMUL** (452) | Multizahlungsauftrag — Sammelmuster mehrerer Einzelzahlungen |
| **PAYORD** (450) | Einzelzahlungsauftrag |
| **PAYEXT** (455) | Erweiterter Zahlungsauftrag |
| **DEBADV** (479) | Belastungsavis |
| **CREEXT** (462) | Erweiterter Gutschriftauftrag |
| **CREMUL** (454) | Sammelmuster Gutschriften |
| **DEBMUL** (453) | Sammelmuster Belastungen |
| **BANSTA** (391) | Kontoauszug |
| **DIRDEB** (431) | Lastschrifteinzug (Mandat-Referenz Pflicht) |
| **FINCAN** (456) | Finanz-Stornierung (Transaktionskennzeichen Pflicht) |
| **DOCAPP** (760) | Akkreditiv-Eröffnungsantrag |
| **DOCINF** (763) | Akkreditiv-Information |
import std.edi.payment;
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_PAY_HDR_SIZE);
var i: int64 := 0;
while (i < EDI_PAY_HDR_SIZE) { poke8(hdr + i, 0); i := i + 1; }
poke64(hdr + EDI_PAY_HDR_REF, "AVIS-2026-0091"c as int64);
poke64(hdr + EDI_PAY_HDR_REFLEN, 14);
poke64(hdr + EDI_PAY_HDR_DATE, "20260813"c as int64);
poke64(hdr + EDI_PAY_HDR_DATELEN, 8);
poke64(hdr + EDI_PAY_HDR_AMOUNT, 88870); // 888,70 EUR
poke64(hdr + EDI_PAY_HDR_CURRENCY, "EUR"c as int64);
poke64(hdr + EDI_PAY_HDR_CURLEN, 3);
poke64(hdr + EDI_PAY_HDR_CREDIBAN, "DE89370400440532013000"c as int64);
poke64(hdr + EDI_PAY_HDR_CREDILEN, 22);
poke64(hdr + EDI_PAY_HDR_BIC, "COBADEFFXXX"c as int64);
poke64(hdr + EDI_PAY_HDR_BICLEN, 11);
poke64(hdr + EDI_PAY_HDR_INVOICEREF, "RE-2026-4711"c as int64);
poke64(hdr + EDI_PAY_HDR_INVOICELEN, 12);
// Bankdaten selbst pruefen - die Write-Funktionen tun es nicht
PrintLn(StrConcat("IBAN gueltig: ", IntToStr(EdiIbanCheck(peek64(hdr + EDI_PAY_HDR_CREDIBAN), 22))));
PrintLn(StrConcat("BIC gueltig: ", IntToStr(EdiBicCheck(peek64(hdr + EDI_PAY_HDR_BIC), 11))));
PrintLn(StrConcat("REMADV-Pflichtfelder (0 = ok): ", IntToStr(EdiRemadvCheck(hdr))));
var out: int64 := alloc(4096);
var n: int64 := EdiRemadvWrite(hdr, out, 4096);
PrintLn(Feld(out, n));
var hdr2: int64 := alloc(EDI_PAY_HDR_SIZE);
EdiRemadvRead(out, n, hdr2);
PrintLn(StrConcat("Betrag/100: ", IntToStr(peek64(hdr2 + EDI_PAY_HDR_AMOUNT))));
// PAYMUL: Sammelauftrag mit zwei Einzelzahlungen
var items: int64 := alloc(2 * EDI_PAYMUL_ITEM_SIZE);
i := 0;
while (i < 2 * EDI_PAYMUL_ITEM_SIZE) { poke8(items + i, 0); i := i + 1; }
poke64(items + EDI_PAYMUL_ITEM_AMOUNT, 50000);
poke64(items + EDI_PAYMUL_ITEM_REF, "LOHN-08-001"c as int64);
poke64(items + EDI_PAYMUL_ITEM_REFLEN, 11);
poke64(items + EDI_PAYMUL_ITEM_CREDIBAN, "DE89370400440532013000"c as int64);
poke64(items + EDI_PAYMUL_ITEM_CREDILEN, 22);
var it1: int64 := items + EDI_PAYMUL_ITEM_SIZE;
poke64(it1 + EDI_PAYMUL_ITEM_AMOUNT, 38870);
poke64(it1 + EDI_PAYMUL_ITEM_REF, "LOHN-08-002"c as int64);
poke64(it1 + EDI_PAYMUL_ITEM_REFLEN, 11);
poke64(it1 + EDI_PAYMUL_ITEM_CREDIBAN, "DE89370400440532013000"c as int64);
poke64(it1 + EDI_PAYMUL_ITEM_CREDILEN, 22);
// Achtung: EdiRemadvWrite hat BGMQUAL im Kopf auf 481 gesetzt.
// EdiPaymulWrite setzt 452 nur, wenn das Feld 0 ist - also zuruecksetzen.
poke64(hdr + EDI_PAY_HDR_BGMQUAL, 0);
// Summe im Kopf muss der Summe der Posten entsprechen
PrintLn(StrConcat("PAYMUL-Summenpruefung (0 = ok): ", IntToStr(EdiPaymulValidate(hdr, items, 2))));
n := EdiPaymulWrite(hdr, items, 2, out, 4096);
PrintLn(Feld(out, n));
return 0;
}
IBAN gueltig: 1
BIC gueltig: 1
REMADV-Pflichtfelder (0 = ok): 0
BGM+481+AVIS-2026-0091+9'DTM+137:20260813:102'FII+CR+DE89370400440532013000:COBADEFFXXX:25'CUX+2:EUR:4'MOA+9:888.70'RFF+IV:RE-2026-4711'CNT+2:1'
Betrag/100: 88870
PAYMUL-Summenpruefung (0 = ok): 0
BGM+452+AVIS-2026-0091+9'DTM+137:20260813:102'FII+CR+DE89370400440532013000:COBADEFFXXX:25'CUX+2:EUR:4'MOA+9:888.70'LIN+1'RFF+CN:LOHN-08-001'FII+OR+DE89370400440532013000::25'MOA+203:500.00'LIN+2'RFF+CN:LOHN-08-002'FII+OR+DE89370400440532013000::25'MOA+203:388.70'CNT+2:2'
Die Bankverbindung steht im ''FII''-Segment (''CR'' Gläubiger, ''OR'' Auftraggeber) im Format ''IBAN:BIC:25''; ''MOA+9'' ist der Gesamt-, ''MOA+203'' der Einzelbetrag.
----
===== Imports =====
* ''std.edi.core''
* ''std.alloc''
----
===== Structs =====
==== EdiPayHdr (EDI_PAY_HDR_SIZE = 160 Bytes) ====
Gemeinsamer Header für alle 13 Nachrichtentypen.
^ Offset-Konstante ^ Inhalt ^
| ''EDI_PAY_HDR_BGMQUAL'' | BGM-Qualifier (automatisch gesetzt durch Write-Funktionen) |
| ''EDI_PAY_HDR_REF / EDI_PAY_HDR_REFLEN'' | Zahlungs-/Auftragsreferenz |
| ''EDI_PAY_HDR_DATE / EDI_PAY_HDR_DATELEN'' | Buchungsdatum "YYYYMMDD" |
| ''EDI_PAY_HDR_AMOUNT'' | Betrag × 100 (MOA+9) |
| ''EDI_PAY_HDR_CURRENCY / EDI_PAY_HDR_CURLEN'' | Währungscode |
| ''EDI_PAY_HDR_CREDIBAN / EDI_PAY_HDR_CREDILEN'' | IBAN Empfänger (FII+CR) |
| ''EDI_PAY_HDR_DEBTIBAN / EDI_PAY_HDR_DEBTILEN'' | IBAN Auftraggeber (FII+DB) |
| ''EDI_PAY_HDR_BIC / EDI_PAY_HDR_BICLEN'' | BIC Empfängerbank |
| ''EDI_PAY_HDR_MANDATEREF / EDI_PAY_HDR_MANDATELEN'' | DIRDEB: Mandatsreferenz (RFF+MR) |
| ''EDI_PAY_HDR_INVOICEREF / EDI_PAY_HDR_INVOICELEN'' | REMADV: Rechnungsreferenz (RFF+IV) |
| ''EDI_PAY_HDR_TXNREF / EDI_PAY_HDR_TXNREFLEN'' | FINCAN: Transaktionskennzeichen (RFF+TN) |
==== EdiPaymulItem (EDI_PAYMUL_ITEM_SIZE = 56 Bytes) ====
Eine Einzelzahlung innerhalb eines PAYMUL/CREMUL/DEBMUL.
^ Offset-Konstante ^ Inhalt ^
| ''EDI_PAYMUL_ITEM_AMOUNT'' | Betrag × 100 (MOA+203) |
| ''EDI_PAYMUL_ITEM_REF / EDI_PAYMUL_ITEM_REFLEN'' | Referenz dieser Zahlung (RFF+CN) |
| ''EDI_PAYMUL_ITEM_DEBTIBAN / EDI_PAYMUL_ITEM_DEBTILEN'' | IBAN Auftraggeber dieser Position |
| ''EDI_PAYMUL_ITEM_CREDIBAN / EDI_PAYMUL_ITEM_CREDILEN'' | IBAN Empfänger dieser Position |
==== EdiDocappHdr (EDI_DOCAPP_HDR_SIZE = 88 Bytes) ====
Akkreditiv-Kopf (DOCAPP/DOCINF).
^ Offset-Konstante ^ Inhalt ^
| ''EDI_DOCAPP_HDR_CREDITNUM / EDI_DOCAPP_HDR_CREDITNUMLEN'' | Akkreditivnummer |
| ''EDI_DOCAPP_HDR_BENEFICIARY / EDI_DOCAPP_HDR_BENEFLEN'' | Begünstigter (NAD+BF) |
| ''EDI_DOCAPP_HDR_BANKBIC / EDI_DOCAPP_HDR_BANKBICLEN'' | BIC der akkreditivstellenden Bank |
| ''EDI_DOCAPP_HDR_AMOUNT'' | Akkreditivbetrag × 100 |
| ''EDI_DOCAPP_HDR_CURRENCY / EDI_DOCAPP_HDR_CURLEN'' | Währung |
| ''EDI_DOCAPP_HDR_VALIDUNTIL / EDI_DOCAPP_HDR_VALIDUNTILLEN'' | Gültig bis "YYYYMMDD" (DTM+36) |
==== EdiDocappDoc (EDI_DOCAPP_DOC_SIZE = 24 Bytes) ====
Ein Akkreditiv-Dokument (z. B. Konnossement, Packzettel).
^ Offset-Konstante ^ Inhalt ^
| ''EDI_DOCAPP_DOC_CODE / EDI_DOCAPP_DOC_CODELEN'' | Dokumentencode |
| ''EDI_DOCAPP_DOC_COPIES'' | Anzahl Kopien |
----
===== Validierungsfunktionen =====
^ Signatur ^ Beschreibung ^
| ''EdiIbanCheck(ptr: int64, len: int64): int64'' | IBAN MOD-97-Prüfung. Gibt 1=gültig, 0=ungültig. Erste 4 Zeichen werden ans Ende verschoben, Buchstaben in zweistellige Zahlen umgewandelt. |
| ''EdiBicCheck(ptr: int64, len: int64): int64'' | BIC-Format: 8 oder 11 Zeichen; erste 4 = Bankcode (A-Z), Zeichen 5-6 = ISO-Ländercode (A-Z). Gibt 1=gültig, 0=ungültig. |
| ''EdiRemadvCheck(hdr: int64): int64'' | Gibt 1 (Warnung) wenn keine Rechnungsreferenz (RFF+IV) vorhanden. |
| ''EdiDirdebCheck(hdr: int64): int64'' | Gibt 2 (Fehler) wenn keine Mandatsreferenz (RFF+MR) vorhanden. |
| ''EdiFincanCheck(hdr: int64): int64'' | Gibt 2 (Fehler) wenn kein Transaktionskennzeichen (RFF+TN) vorhanden. |
| ''EdiPaymulValidate(hdr: int64, items: int64, itemCount: int64): int64'' | Prüft ob Summe der Einzelbeträge dem Gesamtbetrag im Header entspricht. Abweichung > 1 Cent → gibt 2. |
----
===== Funktionen =====
==== Einfache Zahlungsnachrichten ====
^ Write-Funktion ^ Read-Funktion ^ Beschreibung ^
| ''EdiRemadvWrite(hdr, out, outMax)'' | ''EdiRemadvRead(buf, bufLen, hdr)'' | Zahlungsavis |
| ''EdiPayordWrite(hdr, out, outMax)'' | ''EdiPayordRead(buf, bufLen, hdr)'' | Einzelzahlungsauftrag |
| ''EdiPayextWrite(hdr, out, outMax)'' | ''EdiPayextRead(buf, bufLen, hdr)'' | Erweiterter Zahlungsauftrag |
| ''EdiDebadvWrite(hdr, out, outMax)'' | ''EdiDebadvRead(buf, bufLen, hdr)'' | Belastungsavis |
| ''EdiCreextWrite(hdr, out, outMax)'' | ''EdiCreextRead(buf, bufLen, hdr)'' | Erweiterter Gutschriftauftrag |
| ''EdiBanstaWrite(hdr, out, outMax)'' | ''EdiBanstaRead(buf, bufLen, hdr)'' | Kontoauszug |
| ''EdiDirdebWrite(hdr, out, outMax)'' | ''EdiDirdebRead(buf, bufLen, hdr)'' | Lastschrifteinzug |
| ''EdiFincanWrite(hdr, out, outMax)'' | ''EdiFincanRead(buf, bufLen, hdr)'' | Finanz-Stornierung |
Alle einfachen Write-Funktionen setzen automatisch den BGM-Qualifier und schreiben die spezifischen Pflicht-Referenzen (REMADV: RFF+IV, DIRDEB: RFF+MR, FINCAN: RFF+TN).
==== Sammel-Zahlungsnachrichten ====
^ Write-Funktion ^ Read-Funktion ^ Beschreibung ^
| ''EdiPaymulWrite(hdr, items, itemCount, out, outMax)'' | ''EdiPaymulRead(buf, bufLen, hdr, items, maxItems)'' | Sammelmuster Zahlungen |
| ''EdiCremulWrite(hdr, items, itemCount, out, outMax)'' | ''EdiCremulRead(buf, bufLen, hdr, items, maxItems)'' | Sammelmuster Gutschriften |
| ''EdiDebmulWrite(hdr, items, itemCount, out, outMax)'' | ''EdiDebmulRead(buf, bufLen, hdr, items, maxItems)'' | Sammelmuster Belastungen |
==== Akkreditiv ====
^ Signatur ^ Beschreibung ^
| ''EdiDocappWrite(hdr: int64, docs: int64, docCount: int64, out: int64, outMax: int64): int64'' | Schreibt DOCAPP |
| ''EdiDocappRead(buf: int64, bufLen: int64, hdr: int64, docs: int64, maxDocs: int64): int64'' | Parst DOCAPP; gibt Dokumentenanzahl zurück |
| ''EdiDocinfrWrite(hdr: int64, docs: int64, docCount: int64, out: int64, outMax: int64): int64'' | Schreibt DOCINF |
| ''EdiDocinfrRead(buf: int64, bufLen: int64, hdr: int64, docs: int64, maxDocs: int64): int64'' | Parst DOCINF |
----
===== Hinweise =====
* **IBAN im FII-Segment**: Der Wire-Format ist ''IBAN:BIC:25'' — die Zahl 25 ist der EDIFACT-Code für IBAN.
* **BGM-Qualifier: ein Seiteneffekt mit Tücke.** Die einfachen Write-Funktionen (REMADV, PAYORD, PAYEXT, DEBADV, CREEXT, BANSTA, DIRDEB, FINCAN) **schreiben ihren Qualifier in den übergebenen Kopf-Struct**. ''EdiPaymulWrite'', ''EdiCremulWrite'' und ''EdiDebmulWrite'' setzen ihren Wert dagegen nur, wenn das Feld ''0'' ist. Wer denselben Kopf nacheinander für zwei Nachrichtenarten benutzt, muss ''EDI_PAY_HDR_BGMQUAL'' zwischendurch auf ''0'' zurücksetzen — sonst trägt die zweite Nachricht den Qualifier der ersten.
* **Prüf-Funktionen melden Fehler, nicht Erfolg**: ''EdiRemadvCheck'' liefert ''0'' bei gesetzter Rechnungsreferenz und ''1'' ohne; ''EdiDirdebCheck'' (Mandatsreferenz), ''EdiFincanCheck'' (Transaktionsreferenz) und ''EdiPaymulValidate'' (Summenabweichung > 1 Cent) geben ''2'' im Fehlerfall.
* **IBAN und BIC werden nicht automatisch geprüft** — ''EdiIbanCheck'' (MOD-97) und ''EdiBicCheck'' liefern ''1'' für gültig und müssen selbst aufgerufen werden.
* **PAYMUL Gesamtbetrag**: ''EdiPaymulWrite'' schreibt den Wert aus ''EDI_PAY_HDR_AMOUNT'' als MOA+9. ''EdiPaymulValidate'' vergleicht diesen Wert mit der Summe der Item-Beträge.
----
===== Quelldatei =====
^ Unit ^ Datei ^
| ''std.edi.payment'' | ''std/edi/payment.lyx'' |
Letzte Aktualisierung: 2026-08-13 — lauffähiges Beispiel für REMADV und PAYMUL (Sammelauftrag) mit echter Ausgabe (lyxc 1.0.17K); Seiteneffekt der Write-Funktionen auf ''EDI_PAY_HDR_BGMQUAL'' und die Rückgabekonvention der Prüf-Funktionen 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).