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