Verträge / EsOrderState
Shop-Bestellung State
EsOrderState · com.nexoware.connect.events
- Aggregat
- EsOrder
- Topic
- esorder.state je Mandant mit Präfix, z. B.
<mandant>.esorder.state - Key
- EsOrderUuid
- Nachrichtenart
- State — der aktuelle Zustand, ein Writer
- Schreiber
- Shop (shop)
- Leser
- c-entron Webservice (centron) , NEXOWARE.ERP (nexoware-erp)
- Fassung
- Version 1 (neueste)
- Schema-ID
- 63
Vertragsentwurf: vollstaendiger veroeffentlichter Zustand fuer Shop-Bestellung. Feldumfang aus dem archivierten EsOrderChanged; kein fachlicher Vergleich beider Produkte. Direkte Veroeffentlichung durch shop; kein Patch-Pfad. Grenzen, Migration und offene Fachregeln: docs/contracts/esorder.md.
Fassungen
Felder
-
EsOrderUuid Key uuidStabile, global eindeutige Identitaet der Bestellung (Matching-Schluessel; zugleich Message-Key). Der SHOP mintet sie - er ist der Ursprung des Aggregats. Sie ist zugleich der fachliche Idempotenzschluessel, an dem der c-entron-Consumer seine Verknuepfung Bestellung -> Beleg fuehrt: Eine erneute Zustellung trifft auf die vorhandene Verknuepfung, statt einen zweiten Beleg zu erzeugen. Genau das fehlte der Alt-Implementierung, deren Duplikatschutz auf einem nachtraeglich geschriebenen Mapping und einem ES-Statuswechsel beruhte (Inventur Schritt 6, Retry-Risiko).
-
ShopOrderNumber optional stringDefault:
nullBestellnummer, unter der die Bestellung im Shop gefuehrt wird (Quelle ORDER_ID_SHOP) - fachlicher Business-Key, nicht die Identitaet (event-envelope.md). Der Kunde kennt seine Bestellung unter dieser Nummer, und die Alt-Implementierung meldete zu ihr die ERP-Belegnummer zurueck. Vorsorglich optional geschnitten: ob die ES-Quelle sie garantiert, ist nicht verifiziert. -
Status stringDefault:
""Zustand der Bestellung, wie der Shop ihn fuehrt - roh durchgereicht als Zeichenkette der Quelle. Belegt sind aus der Inventur new (neu), openpayment (offene Zahlung) und open (in Bearbeitung); die Alt-Implementierung importierte die ersten beiden und schrieb danach open zurueck. Das Feld heisst bewusst NICHT State: Das State des Korpus ist ein int-Statusfeld mit vertraglich festgelegten Zahlenwerten, die ES-Quelle liefert dagegen Namen. Ein int erzwaenge eine Abbildung, die kein Dokument festlegt; ein Avro-Enum verlangte die vollstaendige Wertemenge, und die ist nicht bekannt (die Inventur nennt drei Werte, nicht den Katalog). Was aus dem Status folgt - ob der Consumer einen Beleg anlegt oder wartet -, entscheidet der Consumer. Ist die Wertemenge quellseitig abgeschlossen, gehoert sie in ein Enum nachgezogen, wie die Rechenart der Sonderpreis-Regel (ADR-0018, Punkt 3). -
Default:
"00000000-0000-0000-0000-000000000000"Referenz auf den Geschaeftspartner, der bestellt hat, ueber dessen UUID (Quelle BuyerPartyId ueber den ES-Kunden). Parent-Referenz und damit Pflicht: kann der Producer sie nicht aufloesen, scheitert er laut, statt still null zu senden (event-envelope.md). Genau dieses Verhalten hatte die Alt-Implementierung fachlich schon - sie uebersprang einen Auftrag, dessen Kunde sich nicht aufloesen liess -, nur still und mit Wiederholung beim naechsten Lauf. Das Read-back-Mapping ueber erp_customerid entfaellt: ueber den Vertrag reist die UUID. -
OrderDate timestampDefault:
0Zeitpunkt, zu dem die Bestellung im Shop aufgegeben wurde, als UTC-Instant. Als Pflicht geschnitten: eine Bestellung ohne Aufgabezeitpunkt ist keine, und der Consumer braucht ihn als Belegdatum. Nicht zu verwechseln mit ChangedAt - das ist der Zeitpunkt DIESES Snapshots und aendert sich bei jeder spaeteren Aenderung der Bestellung. Die quellseitige Nullability ist nicht verifiziert. -
DesiredDeliveryDate optional timestampDefault:
nullVom Besteller gewuenschter Liefertermin als UTC-Instant; die Alt-Implementierung schrieb ihn beim Import in den Belegkopf. Optional - ein Wunschtermin ist eine Angabe, keine Pflicht. -
CurrencyIso optional stringDefault:
nullISO-Waehrungskennzeichen der Bestellung. Feldname und Form wie am Beleg (OrderState.CurrencyIso). Einen Umrechnungsfaktor zur Hauswaehrung traegt die Bestellung nicht: er ist ERP-Wahrheit und gehoert zum Beleg, den der Consumer daraus macht. -
PurchaseOrderNumber optional stringDefault:
nullBestellnummer des Kunden (dessen eigene Referenz, nicht die des Shops); die Alt-Implementierung schrieb sie beim Import in den Belegkopf. Feldname wie am Beleg (OrderState.PurchaseOrderNumber). -
Comment optional stringDefault:
nullBemerkung des Bestellers zum Kopf der Bestellung; die Alt-Implementierung schrieb sie beim Import in den Belegkopf. ADR-0015 nennt sie ausdruecklich als eine der Angaben, die beim Schnitt nicht verlorengehen duerfen - sie war der Grund, warum der Beleg-Vertrag im selben Schritt eine Kopf-Bemerkung bekommt (OrderState.Comment). -
Default:
nullReferenz auf die Zahlungskondition der Bestellung ueber deren UUID (Quelle PAYMENT_ID). Dasselbe Konditions-Stammdatum wie am Beleg; die Alt-Implementierung loeste die ES-Kennung ueber ein Konditions-Mapping auf und fiel auf die Default-Kondition zurueck, wenn das misslang. Der Fallback ist Consumer-Entscheidung und nicht Vertragsinhalt: null heisst, dass der Shop keine Kondition mitgibt. -
Default:
nullReferenz auf die Lieferbedingung der Bestellung ueber deren UUID (Quelle SHIPMENT_ID) - dasselbe Konditions-Stammdatum wie AssetConditionUuid (references am Feld), wie am Beleg. Null, wenn der Shop keine mitgibt. -
GrossTotal optional decimal(18,2)Default:
nullBrutto-Gesamtsumme der Bestellung, beim Publish kaufmaennisch auf 2 Nachkommastellen gerundet. Nur brutto: Der Shop rechnet in Bruttopreisen, und die Brutto-Netto-Umrechnung ist Consumer-Arbeit (ADR-0015, Punkt 3). Ein Netto-Feld hier hiesse, den Producer eine Rechnung anstellen zu lassen, deren Ergebnis der Konsument verantwortet. -
CustomerDiscountPercent optional decimal(6,2)Default:
nullKundenrabatt in Prozent auf die gesamte Bestellung. Die Alt-Implementierung machte daraus eine negative Belegposition auf den RABATT-Artikel und rechnete den Brutto-Wert vorher auf netto um - beides ist Uebersetzung in Beleg-Wahrheit und gehoert zum Consumer. Ueber den Vertrag reist der Rabatt als das, was er im Shop ist: ein Satz am Kopf. -
OrderDiscountPercent optional decimal(6,2)Default:
nullAuftragsrabatt in Prozent, zusaetzlich zum Kundenrabatt. Wie dieser eine Kopf-Angabe des Shops, keine Belegposition. -
VoucherAmountGross optional decimal(18,2)Default:
nullEingeloester Gutschein als Brutto-Betrag (nicht als Satz). Positiv geschnitten: Es reist der Wert des Gutscheins, nicht seine Wirkung auf den Beleg - dass daraus eine negative Position wird, entscheidet der Consumer. -
FreightAmountNet optional decimal(18,2)Default:
nullFrachtkosten als Netto-Betrag. Anders als die Rabatte liefert der Shop die Zuschlaege netto - der Feldname sagt es deshalb ausdruecklich, damit niemand die beiden Seiten gleich behandelt. Welcher Artikel im Beleg daraus wird (Fracht-Artikel aus den Beleg-Einstellungen), ist Consumer-Wissen. -
SmallQuantitySurchargeNet optional decimal(18,2)Default:
nullMindermengenzuschlag als Netto-Betrag. Die Alt-Implementierung suchte dafuer einen Eigenartikel ueber seinen Namen und fiel auf den Platzhalter ARTIKELNEU zurueck, wenn sie ihn nicht fand - eine Suchkette, die zum Consumer wandert. -
Surcharge1Net optional decimal(18,2)Default:
nullErster allgemeiner Aufschlag als Netto-Betrag (Quelle Aufschlag 1). Wofuer er steht, legt der Shop-Betreiber fest; der Vertrag deutet ihn nicht. -
Surcharge2Net optional decimal(18,2)Default:
nullZweiter allgemeiner Aufschlag als Netto-Betrag (Quelle Aufschlag 2). -
DeliveryAddress optional EsOrderDeliveryAddressDefault:
nullLieferziel der Bestellung, so wie der Shop es kennt. Eingebettet und nicht bloss referenziert: Der Besteller kann im Shop eine Anschrift eingeben, die es im ERP noch gar nicht gibt - eine reine Referenz liesse die Bestellung dann ohne Lieferziel durchgehen. Die optionale AddressUuid darin deckt den anderen Fall ab: Hat der Besteller eine bekannte Anschrift seines Kunden gewaehlt, reist sie als Referenz mit, und der Consumer nimmt die Referenz statt der Werte. Das Adress-Mapping der Alt-Implementierung (DELIVERY_PARTY_ID ueber ObjectExternalReferences) entfaellt damit. Null, wenn die Bestellung an die Standardanschrift des Kunden geht. PERSONENBEZUG: siehe doc des Records.9 Felder von
EsOrderDeliveryAddress-
Default:
nullReferenz auf die Anschrift des Geschaeftspartners ueber deren UUID (AddressState), wenn der Besteller eine im ERP bekannte Anschrift gewaehlt hat. Null bei einer im Shop frei eingegebenen Lieferadresse - dann gelten die Werte darunter. -
CompanyName optional stringDefault:
nullFirmenname des Lieferziels. -
ContactName optional stringDefault:
nullName der Person, an die geliefert werden soll. -
Department optional stringDefault:
nullAbteilung. -
Street optional stringDefault:
nullStrasse. -
HouseNumber optional stringDefault:
nullHausnummer. Ob die ES-Quelle Strasse und Hausnummer getrennt fuehrt, ist nicht verifiziert - liefert sie eine gemeinsame Zeile, traegt Street sie und HouseNumber bleibt null. -
Zip optional stringDefault:
nullPostleitzahl. -
City optional stringDefault:
nullOrt. -
CountryIso optional stringDefault:
nullISO-Laenderkennzeichen des Lieferziels - als Code, nicht als Referenz auf das Laender-Stammdatum. Der Shop kennt Laendercodes, keine c-entron-UUIDs; die Aufloesung auf CountryState ist Teil der Uebersetzung und gehoert zum Consumer. Feldform wie CurrencyIso am Kopf.
-
-
Positions Liste EsOrderPosition[]Default:
[]Eingebettete Positionsliste der Bestellung, aufsteigend nach PositionNumber. Voll-Snapshot: der Consumer ersetzt die Collection je Event vollstaendig (kein positionsweises Mergen) - dieselbe Regel wie bei den Belegarten. Default [] nur fuer Schema-Evolution. Die Positionen tragen ausschliesslich Shop-Wahrheit: Was daraus im Beleg wird - Artikel-Identifikation ueber die sechsstufige Suchkette, Platzhalter FREMD/ARTIKELNEU bei unaufloesbaren Zeilen, Netto-Preis, Lager, Steuersatz-Stammdatum -, entscheidet der c-entron-Consumer (ADR-0015, Punkt 3). Bleibt eine Zeile dort unaufloesbar, wird die Bestellung zum sichtbaren geparkten Zustand statt zum stillen Wiederholungs-Loop (consumer-guidelines Regel 6).10 Felder von
EsOrderPosition[]-
PositionNumber intDefault:
0Positionsnummer innerhalb der Bestellung - SORTIERUNG, nicht Identitaet. Positionen sind damit nicht einzeln adressierbar; Commands auf eingebettete Positionen sind repo-weit unzulaessig (aggregate-declaration.md, Sperrvermerk; ADR-0013, Punkt 7). -
Quantity optional doubleDefault:
nullBestellte Menge. -
UnitPriceGross optional decimal(18,4)Default:
nullBRUTTO-Einzelpreis der Position, beim Publish kaufmaennisch auf 4 Nachkommastellen gerundet - so, wie der Shop ihn dem Kunden angezeigt und berechnet hat. Der Beleg fuehrt an derselben Stelle einen Netto-Preis (OrderState.Positions.BasePrice); die Umrechnung liegt dazwischen und gehoert zum Consumer. Der Feldname sagt die Seite ausdruecklich, damit die beiden nicht verwechselt werden. -
VatRate optional decimal(6,2)Default:
nullMehrwertsteuersatz der Position in Prozent, wie der Shop ihn gerechnet hat. Es reist der SATZ, nicht die Referenz auf das Steuersatz-Stammdatum: Der Shop kennt Prozentwerte, die Zuordnung zum ValueAddedTax-Aggregat traf in der Alt-Implementierung der Sync ueber die USt-Liste des ERP - auch das ist Uebersetzung und wandert zum Consumer. -
Ean optional stringDefault:
nullEAN/GTIN des bestellten Artikels - vierte Stufe der Artikel-Suchkette der Alt-Implementierung. Einer von vier Identifikatoren, die eine Position tragen kann; welcher davon gesetzt ist, haengt am Artikel und am Shop-Katalog. -
SupplierArticleNumber optional stringDefault:
nullLieferanten-Artikelnummer (Quelle SUPPLIER_AID) - zweite und dritte Stufe der Suchkette. Traegt sie das Praefix CEN-, meinte die Alt-Implementierung damit einen c-entron-Artikelcode; ohne Praefix einen fremden. Diese Deutung ist Consumer-Wissen, der Vertrag reicht die Nummer roh durch. -
ShopArticleNumber optional stringDefault:
nullArtikelnummer des Shops (Quelle SHOP_AID) - fuenfte Stufe der Suchkette, ebenfalls mit der CEN-Praefix-Deutung beim Consumer. -
Default:
nullReferenz auf das Artikel-Stammdatum ueber dessen UUID, wenn der Shop den ERP-Artikel kennt - die erste und sicherste Stufe der Suchkette (in der Alt-Implementierung die I3D in ERP_AID). Ist sie gesetzt, entfaellt die Suche; ist sie null, arbeitet der Consumer die uebrigen Identifikatoren ab. -
Text optional stringDefault:
nullPositionstext, wie er im Shop steht (Artikelbezeichnung oder Freitext). -
Default:
nullReferenz auf die Kostenstelle der Position ueber deren UUID. Die Alt-Implementierung fuellte sie beim Anlegen der Belegposition; ADR-0015 nennt die Kostenstellen-Zuordnung ausdruecklich als Angabe, die beim Schnitt nicht verlorengehen darf - sie war der Grund, warum der Beleg-Vertrag im selben Schritt eine Positions-Kostenstelle bekommt (OrderState.Positions.CostCenterUuid). Aus welcher Angabe der Bestellung sie stammt, ist nicht verifiziert; die Inventur fuehrt die Positionen mit einem UDX-Block, dessen Inhalt sie nicht aufschluesselt.
-
-
Revision longStreng monotone Revision je Objekt, vom publizierenden Produkt bei einer Zustandsaenderung erhoeht und zusammen mit der Outbox persistiert. Wiederholungen behalten die Revision.
-
LastEventId ↗ extern: LastEventId uuidStabile EventId des zuletzt publizierten Zustands; bei Wiederholung derselben Outbox-Nachricht identisch.
-
Default:
nullUUID des aendernden Mitarbeiters (Employee); null, wenn unbekannt. Hier praktisch immer null: Eine Bestellung gibt ein Kunde im Shop auf, kein c-entron-Mitarbeiter. Das Feld bleibt trotzdem Teil des Umschlags, weil ADR-0016, Punkt 3 fuer Aggregate mit Ursprung ausserhalb von c-entron dieselbe Mechanik verlangt wie beim groessten Beleg. -
ChangedAt timestampZeitpunkt DIESER Aenderung als UTC-Instant - nicht der Zeitpunkt, zu dem die Bestellung aufgegeben wurde (dafuer OrderDate). Eine spaetere Shop-seitige Aenderung reist als neuer Voll-Snapshot desselben Aggregats mit neuem ChangedAt (event-envelope.md, Granularitaet).
Referenziert von
Rohfassung
Schema dieser Fassung (Avro)
{
"type": "record",
"name": "EsOrderState",
"namespace": "com.nexoware.connect.events",
"doc": "Vertragsentwurf: vollstaendiger veroeffentlichter Zustand fuer Shop-Bestellung. Feldumfang aus dem archivierten EsOrderChanged; kein fachlicher Vergleich beider Produkte. Direkte Veroeffentlichung durch shop; kein Patch-Pfad. Grenzen, Migration und offene Fachregeln: docs/contracts/esorder.md.",
"fields": [
{
"name": "EsOrderUuid",
"type": {
"type": "string",
"logicalType": "uuid"
},
"doc": "Stabile, global eindeutige Identitaet der Bestellung (Matching-Schluessel; zugleich Message-Key). Der SHOP mintet sie - er ist der Ursprung des Aggregats. Sie ist zugleich der fachliche Idempotenzschluessel, an dem der c-entron-Consumer seine Verknuepfung Bestellung -> Beleg fuehrt: Eine erneute Zustellung trifft auf die vorhandene Verknuepfung, statt einen zweiten Beleg zu erzeugen. Genau das fehlte der Alt-Implementierung, deren Duplikatschutz auf einem nachtraeglich geschriebenen Mapping und einem ES-Statuswechsel beruhte (Inventur Schritt 6, Retry-Risiko)."
},
{
"name": "ShopOrderNumber",
"type": [
"null",
"string"
],
"doc": "Bestellnummer, unter der die Bestellung im Shop gefuehrt wird (Quelle ORDER_ID_SHOP) - fachlicher Business-Key, nicht die Identitaet (event-envelope.md). Der Kunde kennt seine Bestellung unter dieser Nummer, und die Alt-Implementierung meldete zu ihr die ERP-Belegnummer zurueck. Vorsorglich optional geschnitten: ob die ES-Quelle sie garantiert, ist nicht verifiziert.",
"default": null
},
{
"name": "Status",
"type": "string",
"doc": "Zustand der Bestellung, wie der Shop ihn fuehrt - roh durchgereicht als Zeichenkette der Quelle. Belegt sind aus der Inventur new (neu), openpayment (offene Zahlung) und open (in Bearbeitung); die Alt-Implementierung importierte die ersten beiden und schrieb danach open zurueck. Das Feld heisst bewusst NICHT State: Das State des Korpus ist ein int-Statusfeld mit vertraglich festgelegten Zahlenwerten, die ES-Quelle liefert dagegen Namen. Ein int erzwaenge eine Abbildung, die kein Dokument festlegt; ein Avro-Enum verlangte die vollstaendige Wertemenge, und die ist nicht bekannt (die Inventur nennt drei Werte, nicht den Katalog). Was aus dem Status folgt - ob der Consumer einen Beleg anlegt oder wartet -, entscheidet der Consumer. Ist die Wertemenge quellseitig abgeschlossen, gehoert sie in ein Enum nachgezogen, wie die Rechenart der Sonderpreis-Regel (ADR-0018, Punkt 3).",
"default": ""
},
{
"name": "AccountUuid",
"type": {
"type": "string",
"logicalType": "uuid"
},
"doc": "Referenz auf den Geschaeftspartner, der bestellt hat, ueber dessen UUID (Quelle BuyerPartyId ueber den ES-Kunden). Parent-Referenz und damit Pflicht: kann der Producer sie nicht aufloesen, scheitert er laut, statt still null zu senden (event-envelope.md). Genau dieses Verhalten hatte die Alt-Implementierung fachlich schon - sie uebersprang einen Auftrag, dessen Kunde sich nicht aufloesen liess -, nur still und mit Wiederholung beim naechsten Lauf. Das Read-back-Mapping ueber erp_customerid entfaellt: ueber den Vertrag reist die UUID.",
"default": "00000000-0000-0000-0000-000000000000"
},
{
"name": "OrderDate",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
},
"doc": "Zeitpunkt, zu dem die Bestellung im Shop aufgegeben wurde, als UTC-Instant. Als Pflicht geschnitten: eine Bestellung ohne Aufgabezeitpunkt ist keine, und der Consumer braucht ihn als Belegdatum. Nicht zu verwechseln mit ChangedAt - das ist der Zeitpunkt DIESES Snapshots und aendert sich bei jeder spaeteren Aenderung der Bestellung. Die quellseitige Nullability ist nicht verifiziert.",
"default": 0
},
{
"name": "DesiredDeliveryDate",
"type": [
"null",
{
"type": "long",
"logicalType": "timestamp-millis"
}
],
"doc": "Vom Besteller gewuenschter Liefertermin als UTC-Instant; die Alt-Implementierung schrieb ihn beim Import in den Belegkopf. Optional - ein Wunschtermin ist eine Angabe, keine Pflicht.",
"default": null
},
{
"name": "CurrencyIso",
"type": [
"null",
"string"
],
"doc": "ISO-Waehrungskennzeichen der Bestellung. Feldname und Form wie am Beleg (OrderState.CurrencyIso). Einen Umrechnungsfaktor zur Hauswaehrung traegt die Bestellung nicht: er ist ERP-Wahrheit und gehoert zum Beleg, den der Consumer daraus macht.",
"default": null
},
{
"name": "PurchaseOrderNumber",
"type": [
"null",
"string"
],
"doc": "Bestellnummer des Kunden (dessen eigene Referenz, nicht die des Shops); die Alt-Implementierung schrieb sie beim Import in den Belegkopf. Feldname wie am Beleg (OrderState.PurchaseOrderNumber).",
"default": null
},
{
"name": "Comment",
"type": [
"null",
"string"
],
"doc": "Bemerkung des Bestellers zum Kopf der Bestellung; die Alt-Implementierung schrieb sie beim Import in den Belegkopf. ADR-0015 nennt sie ausdruecklich als eine der Angaben, die beim Schnitt nicht verlorengehen duerfen - sie war der Grund, warum der Beleg-Vertrag im selben Schritt eine Kopf-Bemerkung bekommt (OrderState.Comment).",
"default": null
},
{
"name": "AssetConditionUuid",
"type": [
"null",
{
"type": "string",
"logicalType": "uuid"
}
],
"doc": "Referenz auf die Zahlungskondition der Bestellung ueber deren UUID (Quelle PAYMENT_ID). Dasselbe Konditions-Stammdatum wie am Beleg; die Alt-Implementierung loeste die ES-Kennung ueber ein Konditions-Mapping auf und fiel auf die Default-Kondition zurueck, wenn das misslang. Der Fallback ist Consumer-Entscheidung und nicht Vertragsinhalt: null heisst, dass der Shop keine Kondition mitgibt.",
"default": null
},
{
"name": "DeliveryConditionUuid",
"type": [
"null",
{
"type": "string",
"logicalType": "uuid"
}
],
"doc": "Referenz auf die Lieferbedingung der Bestellung ueber deren UUID (Quelle SHIPMENT_ID) - dasselbe Konditions-Stammdatum wie AssetConditionUuid (references am Feld), wie am Beleg. Null, wenn der Shop keine mitgibt.",
"default": null,
"references": "AssetCondition"
},
{
"name": "GrossTotal",
"type": [
"null",
{
"type": "bytes",
"logicalType": "decimal",
"precision": 18,
"scale": 2
}
],
"doc": "Brutto-Gesamtsumme der Bestellung, beim Publish kaufmaennisch auf 2 Nachkommastellen gerundet. Nur brutto: Der Shop rechnet in Bruttopreisen, und die Brutto-Netto-Umrechnung ist Consumer-Arbeit (ADR-0015, Punkt 3). Ein Netto-Feld hier hiesse, den Producer eine Rechnung anstellen zu lassen, deren Ergebnis der Konsument verantwortet.",
"default": null
},
{
"name": "CustomerDiscountPercent",
"type": [
"null",
{
"type": "bytes",
"logicalType": "decimal",
"precision": 6,
"scale": 2
}
],
"doc": "Kundenrabatt in Prozent auf die gesamte Bestellung. Die Alt-Implementierung machte daraus eine negative Belegposition auf den RABATT-Artikel und rechnete den Brutto-Wert vorher auf netto um - beides ist Uebersetzung in Beleg-Wahrheit und gehoert zum Consumer. Ueber den Vertrag reist der Rabatt als das, was er im Shop ist: ein Satz am Kopf.",
"default": null
},
{
"name": "OrderDiscountPercent",
"type": [
"null",
{
"type": "bytes",
"logicalType": "decimal",
"precision": 6,
"scale": 2
}
],
"doc": "Auftragsrabatt in Prozent, zusaetzlich zum Kundenrabatt. Wie dieser eine Kopf-Angabe des Shops, keine Belegposition.",
"default": null
},
{
"name": "VoucherAmountGross",
"type": [
"null",
{
"type": "bytes",
"logicalType": "decimal",
"precision": 18,
"scale": 2
}
],
"doc": "Eingeloester Gutschein als Brutto-Betrag (nicht als Satz). Positiv geschnitten: Es reist der Wert des Gutscheins, nicht seine Wirkung auf den Beleg - dass daraus eine negative Position wird, entscheidet der Consumer.",
"default": null
},
{
"name": "FreightAmountNet",
"type": [
"null",
{
"type": "bytes",
"logicalType": "decimal",
"precision": 18,
"scale": 2
}
],
"doc": "Frachtkosten als Netto-Betrag. Anders als die Rabatte liefert der Shop die Zuschlaege netto - der Feldname sagt es deshalb ausdruecklich, damit niemand die beiden Seiten gleich behandelt. Welcher Artikel im Beleg daraus wird (Fracht-Artikel aus den Beleg-Einstellungen), ist Consumer-Wissen.",
"default": null
},
{
"name": "SmallQuantitySurchargeNet",
"type": [
"null",
{
"type": "bytes",
"logicalType": "decimal",
"precision": 18,
"scale": 2
}
],
"doc": "Mindermengenzuschlag als Netto-Betrag. Die Alt-Implementierung suchte dafuer einen Eigenartikel ueber seinen Namen und fiel auf den Platzhalter ARTIKELNEU zurueck, wenn sie ihn nicht fand - eine Suchkette, die zum Consumer wandert.",
"default": null
},
{
"name": "Surcharge1Net",
"type": [
"null",
{
"type": "bytes",
"logicalType": "decimal",
"precision": 18,
"scale": 2
}
],
"doc": "Erster allgemeiner Aufschlag als Netto-Betrag (Quelle Aufschlag 1). Wofuer er steht, legt der Shop-Betreiber fest; der Vertrag deutet ihn nicht.",
"default": null
},
{
"name": "Surcharge2Net",
"type": [
"null",
{
"type": "bytes",
"logicalType": "decimal",
"precision": 18,
"scale": 2
}
],
"doc": "Zweiter allgemeiner Aufschlag als Netto-Betrag (Quelle Aufschlag 2).",
"default": null
},
{
"name": "DeliveryAddress",
"type": [
"null",
{
"type": "record",
"name": "EsOrderDeliveryAddress",
"fields": [
{
"name": "AddressUuid",
"type": [
"null",
{
"type": "string",
"logicalType": "uuid"
}
],
"doc": "Referenz auf die Anschrift des Geschaeftspartners ueber deren UUID (AddressState), wenn der Besteller eine im ERP bekannte Anschrift gewaehlt hat. Null bei einer im Shop frei eingegebenen Lieferadresse - dann gelten die Werte darunter.",
"default": null
},
{
"name": "CompanyName",
"type": [
"null",
"string"
],
"doc": "Firmenname des Lieferziels.",
"default": null
},
{
"name": "ContactName",
"type": [
"null",
"string"
],
"doc": "Name der Person, an die geliefert werden soll.",
"default": null
},
{
"name": "Department",
"type": [
"null",
"string"
],
"doc": "Abteilung.",
"default": null
},
{
"name": "Street",
"type": [
"null",
"string"
],
"doc": "Strasse.",
"default": null
},
{
"name": "HouseNumber",
"type": [
"null",
"string"
],
"doc": "Hausnummer. Ob die ES-Quelle Strasse und Hausnummer getrennt fuehrt, ist nicht verifiziert - liefert sie eine gemeinsame Zeile, traegt Street sie und HouseNumber bleibt null.",
"default": null
},
{
"name": "Zip",
"type": [
"null",
"string"
],
"doc": "Postleitzahl.",
"default": null
},
{
"name": "City",
"type": [
"null",
"string"
],
"doc": "Ort.",
"default": null
},
{
"name": "CountryIso",
"type": [
"null",
"string"
],
"doc": "ISO-Laenderkennzeichen des Lieferziels - als Code, nicht als Referenz auf das Laender-Stammdatum. Der Shop kennt Laendercodes, keine c-entron-UUIDs; die Aufloesung auf CountryState ist Teil der Uebersetzung und gehoert zum Consumer. Feldform wie CurrencyIso am Kopf.",
"default": null
}
]
}
],
"doc": "Lieferziel der Bestellung, so wie der Shop es kennt. Eingebettet und nicht bloss referenziert: Der Besteller kann im Shop eine Anschrift eingeben, die es im ERP noch gar nicht gibt - eine reine Referenz liesse die Bestellung dann ohne Lieferziel durchgehen. Die optionale AddressUuid darin deckt den anderen Fall ab: Hat der Besteller eine bekannte Anschrift seines Kunden gewaehlt, reist sie als Referenz mit, und der Consumer nimmt die Referenz statt der Werte. Das Adress-Mapping der Alt-Implementierung (DELIVERY_PARTY_ID ueber ObjectExternalReferences) entfaellt damit. Null, wenn die Bestellung an die Standardanschrift des Kunden geht. PERSONENBEZUG: siehe doc des Records.",
"default": null
},
{
"name": "Positions",
"type": {
"type": "array",
"items": {
"type": "record",
"name": "EsOrderPosition",
"fields": [
{
"name": "PositionNumber",
"type": "int",
"doc": "Positionsnummer innerhalb der Bestellung - SORTIERUNG, nicht Identitaet. Positionen sind damit nicht einzeln adressierbar; Commands auf eingebettete Positionen sind repo-weit unzulaessig (aggregate-declaration.md, Sperrvermerk; ADR-0013, Punkt 7).",
"default": 0
},
{
"name": "Quantity",
"type": [
"null",
"double"
],
"doc": "Bestellte Menge.",
"default": null
},
{
"name": "UnitPriceGross",
"type": [
"null",
{
"type": "bytes",
"logicalType": "decimal",
"precision": 18,
"scale": 4
}
],
"doc": "BRUTTO-Einzelpreis der Position, beim Publish kaufmaennisch auf 4 Nachkommastellen gerundet - so, wie der Shop ihn dem Kunden angezeigt und berechnet hat. Der Beleg fuehrt an derselben Stelle einen Netto-Preis (OrderState.Positions.BasePrice); die Umrechnung liegt dazwischen und gehoert zum Consumer. Der Feldname sagt die Seite ausdruecklich, damit die beiden nicht verwechselt werden.",
"default": null
},
{
"name": "VatRate",
"type": [
"null",
{
"type": "bytes",
"logicalType": "decimal",
"precision": 6,
"scale": 2
}
],
"doc": "Mehrwertsteuersatz der Position in Prozent, wie der Shop ihn gerechnet hat. Es reist der SATZ, nicht die Referenz auf das Steuersatz-Stammdatum: Der Shop kennt Prozentwerte, die Zuordnung zum ValueAddedTax-Aggregat traf in der Alt-Implementierung der Sync ueber die USt-Liste des ERP - auch das ist Uebersetzung und wandert zum Consumer.",
"default": null
},
{
"name": "Ean",
"type": [
"null",
"string"
],
"doc": "EAN/GTIN des bestellten Artikels - vierte Stufe der Artikel-Suchkette der Alt-Implementierung. Einer von vier Identifikatoren, die eine Position tragen kann; welcher davon gesetzt ist, haengt am Artikel und am Shop-Katalog.",
"default": null
},
{
"name": "SupplierArticleNumber",
"type": [
"null",
"string"
],
"doc": "Lieferanten-Artikelnummer (Quelle SUPPLIER_AID) - zweite und dritte Stufe der Suchkette. Traegt sie das Praefix CEN-, meinte die Alt-Implementierung damit einen c-entron-Artikelcode; ohne Praefix einen fremden. Diese Deutung ist Consumer-Wissen, der Vertrag reicht die Nummer roh durch.",
"default": null
},
{
"name": "ShopArticleNumber",
"type": [
"null",
"string"
],
"doc": "Artikelnummer des Shops (Quelle SHOP_AID) - fuenfte Stufe der Suchkette, ebenfalls mit der CEN-Praefix-Deutung beim Consumer.",
"default": null
},
{
"name": "ArticleUuid",
"type": [
"null",
{
"type": "string",
"logicalType": "uuid"
}
],
"doc": "Referenz auf das Artikel-Stammdatum ueber dessen UUID, wenn der Shop den ERP-Artikel kennt - die erste und sicherste Stufe der Suchkette (in der Alt-Implementierung die I3D in ERP_AID). Ist sie gesetzt, entfaellt die Suche; ist sie null, arbeitet der Consumer die uebrigen Identifikatoren ab.",
"default": null
},
{
"name": "Text",
"type": [
"null",
"string"
],
"doc": "Positionstext, wie er im Shop steht (Artikelbezeichnung oder Freitext).",
"default": null
},
{
"name": "CostCenterUuid",
"type": [
"null",
{
"type": "string",
"logicalType": "uuid"
}
],
"doc": "Referenz auf die Kostenstelle der Position ueber deren UUID. Die Alt-Implementierung fuellte sie beim Anlegen der Belegposition; ADR-0015 nennt die Kostenstellen-Zuordnung ausdruecklich als Angabe, die beim Schnitt nicht verlorengehen darf - sie war der Grund, warum der Beleg-Vertrag im selben Schritt eine Positions-Kostenstelle bekommt (OrderState.Positions.CostCenterUuid). Aus welcher Angabe der Bestellung sie stammt, ist nicht verifiziert; die Inventur fuehrt die Positionen mit einem UDX-Block, dessen Inhalt sie nicht aufschluesselt.",
"default": null
}
]
}
},
"doc": "Eingebettete Positionsliste der Bestellung, aufsteigend nach PositionNumber. Voll-Snapshot: der Consumer ersetzt die Collection je Event vollstaendig (kein positionsweises Mergen) - dieselbe Regel wie bei den Belegarten. Default [] nur fuer Schema-Evolution. Die Positionen tragen ausschliesslich Shop-Wahrheit: Was daraus im Beleg wird - Artikel-Identifikation ueber die sechsstufige Suchkette, Platzhalter FREMD/ARTIKELNEU bei unaufloesbaren Zeilen, Netto-Preis, Lager, Steuersatz-Stammdatum -, entscheidet der c-entron-Consumer (ADR-0015, Punkt 3). Bleibt eine Zeile dort unaufloesbar, wird die Bestellung zum sichtbaren geparkten Zustand statt zum stillen Wiederholungs-Loop (consumer-guidelines Regel 6).",
"default": []
},
{
"name": "Revision",
"type": "long",
"doc": "Streng monotone Revision je Objekt, vom publizierenden Produkt bei einer Zustandsaenderung erhoeht und zusammen mit der Outbox persistiert. Wiederholungen behalten die Revision."
},
{
"name": "LastEventId",
"type": {
"type": "string",
"logicalType": "uuid"
},
"doc": "Stabile EventId des zuletzt publizierten Zustands; bei Wiederholung derselben Outbox-Nachricht identisch."
},
{
"name": "ChangedByUuid",
"type": [
"null",
{
"type": "string",
"logicalType": "uuid"
}
],
"doc": "UUID des aendernden Mitarbeiters (Employee); null, wenn unbekannt. Hier praktisch immer null: Eine Bestellung gibt ein Kunde im Shop auf, kein c-entron-Mitarbeiter. Das Feld bleibt trotzdem Teil des Umschlags, weil ADR-0016, Punkt 3 fuer Aggregate mit Ursprung ausserhalb von c-entron dieselbe Mechanik verlangt wie beim groessten Beleg.",
"default": null,
"references": "Employee"
},
{
"name": "ChangedAt",
"type": {
"type": "long",
"logicalType": "timestamp-millis"
},
"doc": "Zeitpunkt DIESER Aenderung als UTC-Instant - nicht der Zeitpunkt, zu dem die Bestellung aufgegeben wurde (dafuer OrderDate). Eine spaetere Shop-seitige Aenderung reist als neuer Voll-Snapshot desselben Aggregats mit neuem ChangedAt (event-envelope.md, Granularitaet)."
}
],
"aggregate": "EsOrder",
"label": "Shop-Bestellung",
"topic": "esorder.state",
"key": "EsOrderUuid",
"cleanupPolicy": "compact",
"partitions": 1,
"writers": [
"shop"
],
"readers": [
"centron",
"nexoware-erp"
]
}