====== std.edi.rfq ======
Anfrage- und Angebotsprozess per EDIFACT: Käufer sendet eine Angebotsanfrage (REQOTE), Lieferant antwortet mit einem Angebot (QUOTES). Der Kreuzreferenz-Mechanismus über ''RFF+RFQ'' ist Pflicht — jedes QUOTES muss die Nummer des zugehörigen REQOTE tragen.
* **REQOTE** (BGM 311) — Request for Quotation: Artikel, Mengen, Wunsch-Liefertermine
* **QUOTES** (BGM 315) — Quotation: Preise, Verfügbarkeit, Liefertermine
import std.edi.rfq;
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 {
// 1. Anfrage (REQOTE) ueber zwei Artikel
var rl: int64 := alloc(2 * EDI_RFQ_LINE_SIZE);
var i: int64 := 0;
while (i < 2 * EDI_RFQ_LINE_SIZE) { poke8(rl + i, 0); i := i + 1; }
poke64(rl + EDI_RFQ_LINE_GTIN, "04012345678901"c as int64);
poke64(rl + EDI_RFQ_LINE_GTINLEN, 14);
poke64(rl + EDI_RFQ_LINE_QTY, 240);
poke64(rl + EDI_RFQ_LINE_DATE, "20260915"c as int64);
var r1: int64 := rl + EDI_RFQ_LINE_SIZE;
poke64(r1 + EDI_RFQ_LINE_GTIN, "04012345678918"c as int64);
poke64(r1 + EDI_RFQ_LINE_GTINLEN, 14);
poke64(r1 + EDI_RFQ_LINE_QTY, 60);
var out: int64 := alloc(4096);
var n: int64 := EdiReqoteWrite("ANF-2026-0007"c, "20260813"c, rl, 2, out, 4096);
PrintLn(Feld(out, n));
var hdr: int64 := alloc(EDI_RFQHDR_SIZE);
var lin: int64 := alloc(8 * EDI_RFQ_LINE_SIZE);
var cnt: int64 := EdiReqoteRead(out, n, hdr, lin, 8);
PrintLn(StrConcat(StrConcat("Anfrage ", Feld(peek64(hdr + EDI_RFQHDR_NUM), peek64(hdr + EDI_RFQHDR_NUMLEN))),
StrConcat(" mit Positionen: ", IntToStr(cnt))));
// 2. Angebot (QUOTES) - Position 2 nicht lieferbar
var ql: int64 := alloc(2 * EDI_QUOTE_LINE_SIZE);
i := 0;
while (i < 2 * EDI_QUOTE_LINE_SIZE) { poke8(ql + i, 0); i := i + 1; }
poke64(ql + EDI_QUOTE_LINE_GTIN, "04012345678901"c as int64);
poke64(ql + EDI_QUOTE_LINE_GTINLEN, 14);
poke64(ql + EDI_QUOTE_LINE_PRICE, 1899);
poke64(ql + EDI_QUOTE_LINE_CURRENCY, "EUR"c as int64);
poke64(ql + EDI_QUOTE_LINE_CURRENCYLEN, 3);
poke64(ql + EDI_QUOTE_LINE_DATE, "20260920"c as int64);
poke64(ql + EDI_QUOTE_LINE_AVAIL, 1);
var q1: int64 := ql + EDI_QUOTE_LINE_SIZE;
poke64(q1 + EDI_QUOTE_LINE_GTIN, "04012345678918"c as int64);
poke64(q1 + EDI_QUOTE_LINE_GTINLEN, 14);
poke64(q1 + EDI_QUOTE_LINE_AVAIL, 0);
n := EdiQuotesWrite("ANF-2026-0007"c, "ANG-5501"c, ql, 2, out, 4096);
PrintLn(Feld(out, n));
var qhdr: int64 := alloc(EDI_QUOTEHDR_SIZE);
var qlin: int64 := alloc(8 * EDI_QUOTE_LINE_SIZE);
cnt := EdiQuotesRead(out, n, qhdr, qlin, 8);
i := 0;
while (i < cnt) {
var q: int64 := qlin + i * EDI_QUOTE_LINE_SIZE;
if (peek64(q + EDI_QUOTE_LINE_AVAIL) == 1) {
PrintLn(StrConcat(StrConcat("lieferbar: ", Feld(peek64(q + EDI_QUOTE_LINE_GTIN), peek64(q + EDI_QUOTE_LINE_GTINLEN))),
StrConcat(" zu Preis/100 ", IntToStr(peek64(q + EDI_QUOTE_LINE_PRICE)))));
} else {
PrintLn(StrConcat("nicht lieferbar: ", Feld(peek64(q + EDI_QUOTE_LINE_GTIN), peek64(q + EDI_QUOTE_LINE_GTINLEN))));
}
i += 1;
}
return 0;
}
BGM+311+ANF-2026-0007+9'DTM+137:20260813:102'LIN+1++04012345678901:SRV'QTY+21:240'DTM+10:20260915:102'LIN+2++04012345678918:SRV'QTY+21:60'CNT+2:2'
Anfrage ANF-2026-0007 mit Positionen: 2
BGM+315+ANG-5501+9'RFF+RFQ:ANF-2026-0007'LIN+1++04012345678901:SRV'PRI+AAA:18.99:CP'LOC+11:1'DTM+2:20260920:102'LIN+2++04012345678918:SRV'LOC+11:0'CNT+2:2'
lieferbar: 04012345678901 zu Preis/100 1899
nicht lieferbar: 04012345678918
Die Verfügbarkeit steckt im ''LOC+11''-Segment (''1'' = lieferbar, ''0'' = nicht lieferbar); ''RFF+RFQ'' verweist auf die ursprüngliche Anfrage. Eine nicht lieferbare Position trägt weder Preis noch Liefertermin.
----
===== Imports =====
* ''std.edi.core''
* ''std.alloc''
----
===== Structs =====
==== EdiRfqLine (EDI_RFQ_LINE_SIZE = 48 Bytes) ====
Eine Position in einer Angebotsanfrage.
^ Offset-Konstante ^ Inhalt ^
| ''EDI_RFQ_LINE_GTIN / EDI_RFQ_LINE_GTINLEN'' | GTIN-Zeiger und -Länge |
| ''EDI_RFQ_LINE_QTY'' | Angefragte Menge |
| ''EDI_RFQ_LINE_UNIT / EDI_RFQ_LINE_UNITLEN'' | Mengeneinheit (z. B. "PCE", optional) |
| ''EDI_RFQ_LINE_DATE'' | Zeiger auf 8-stelliges Wunschdatum "YYYYMMDD" (0 = keins) |
==== EdiQuoteLine (EDI_QUOTE_LINE_SIZE = 56 Bytes) ====
Eine Position in einem Angebot.
^ Offset-Konstante ^ Inhalt ^
| ''EDI_QUOTE_LINE_GTIN / EDI_QUOTE_LINE_GTINLEN'' | GTIN-Zeiger und -Länge |
| ''EDI_QUOTE_LINE_PRICE'' | Preis × 100 (Festkomma; 1999 = 19,99 €) |
| ''EDI_QUOTE_LINE_CURRENCY / EDI_QUOTE_LINE_CURRENCYLEN'' | Währung (z. B. "EUR") |
| ''EDI_QUOTE_LINE_DATE'' | Zeiger auf Lieferdatum "YYYYMMDD" (0 = keins) |
| ''EDI_QUOTE_LINE_AVAIL'' | Verfügbarkeit: 1 = verfügbar, 0 = nicht verfügbar |
==== EdiRfqHdr (EDI_RFQHDR_SIZE = 32 Bytes) ====
Kopfdaten eines eingehenden REQOTE.
^ Offset-Konstante ^ Inhalt ^
| ''EDI_RFQHDR_NUM / EDI_RFQHDR_NUMLEN'' | RFQ-Nummer (Zeiger in Empfangspuffer) |
| ''EDI_RFQHDR_DATE / EDI_RFQHDR_DATELEN'' | Dokumentdatum |
==== EdiQuoteHdr (EDI_QUOTEHDR_SIZE = 32 Bytes) ====
Kopfdaten eines eingehenden QUOTES.
^ Offset-Konstante ^ Inhalt ^
| ''EDI_QUOTEHDR_NUM / EDI_QUOTEHDR_NUMLEN'' | Angebotsnummer |
| ''EDI_QUOTEHDR_RFQREF / EDI_QUOTEHDR_RFQREFLEN'' | Rückverweis auf REQOTE-Nummer (''RFF+RFQ'') |
----
===== Funktionen =====
==== REQOTE ====
^ Signatur ^ Beschreibung ^
| ''EdiReqoteWrite(rfqNum: int64, date: int64, lines: int64, lineCount: int64, out: int64, outMax: int64): int64'' | Schreibt REQOTE. ''rfqNum'' ist Pflicht (0 → gibt ''-1'' zurück). ''date'' = Zeiger auf "YYYYMMDD" oder 0. |
| ''EdiReqoteRead(buf: int64, bufLen: int64, hdr: int64, lines: int64, maxLines: int64): int64'' | Parst REQOTE; befüllt ''hdr'' (EDI_RFQHDR_SIZE) und ''lines''-Array. Gibt Zeilenanzahl zurück. Zero-Copy: Zeiger in ''hdr/lines'' zeigen in ''buf''. |
==== QUOTES ====
^ Signatur ^ Beschreibung ^
| ''EdiQuotesWrite(rfqRef: int64, quoteNum: int64, lines: int64, lineCount: int64, out: int64, outMax: int64): int64'' | Schreibt QUOTES. ''rfqRef'' ist Pflicht (0 → gibt ''-1'' zurück). ''quoteNum'' = eigene Angebotsnummer (optional, 0 erlaubt). |
| ''EdiQuotesRead(buf: int64, bufLen: int64, hdr: int64, lines: int64, maxLines: int64): int64'' | Parst QUOTES; befüllt ''hdr'' und ''lines''. Gibt Zeilenanzahl zurück. |
----
===== Hinweise =====
* **rfqRef Pflicht in QUOTES**: ''EdiQuotesWrite'' gibt ''-1'' zurück, wenn ''rfqRef'' null oder leer ist. EDIFACT fordert diesen Rückverweis (''RFF+RFQ'') für die Auftragszuordnung.
* **Preise als Festkomma**: Preise werden als ''int64 × 100'' gespeichert. ''1999'' bedeutet ''19,99''. Beim Schreiben wird daraus ''19.99'' im EDIFACT-Format.
* **Datum-Format**: Alle Datum-Felder erwarten genau 8 Zeichen ''YYYYMMDD'' — keine Trennzeichen, kein Längenfeld; ''0'' lässt das DTM-Segment weg.
* **Verfügbarkeit ist Pflichtangabe**: ''EDI_QUOTE_LINE_AVAIL'' wird immer als ''LOC+11'' geschrieben. Bei ''0'' (nicht lieferbar) unterdrückt ''EdiQuotesWrite'' Preis und Liefertermin — ein gesetzter Preis geht dann verloren.
* **Zwei getrennte Zeilen-Structs**: Anfrage (''EDI_RFQ_LINE_*'', 48 Bytes) und Angebot (''EDI_QUOTE_LINE_*'', 56 Bytes) haben unterschiedliche Layouts; die Antwort ist keine Kopie der Anfrage.
* **Structs vor dem Befüllen nullen.**
----
===== Quelldatei =====
^ Unit ^ Datei ^
| ''std.edi.rfq'' | ''std/edi/rfq.lyx'' |
Letzte Aktualisierung: 2026-08-13 — Beispiel deckt jetzt den kompletten Ablauf Anfrage → Angebot ab, ist lauffähig und ausgeführt (lyxc 1.0.17K); Verhalten bei nicht lieferbaren Positionen 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).