# Formate & Normalisierung

Orderport arbeitet nicht direkt mit Ihrem cXML, Shopify-JSON oder EDIFACT-Text. Stattdessen übersetzt es jedes Eingabeformat erst in ein internes, einheitliches Datenmodell – und von dort in Ihr Zielformat. Das macht die Transformation vorhersagbar, testbar und erweiterbar.

## Die vier Schritte

Jede empfangene Bestellung durchläuft diese vier Stufen:

```
Raw Payload → [Normalize] → [Map] → [Serialize] → [Adapt] → Transformed Payload
```

| Stufe | Was passiert? |
|---|---|
| **Normalize** | Quell-Payload wird in eine kanonische Zwischenform übersetzt |
| **Map** | Ihre Mapping-Regeln zeichnen Felder vom Quell- auf das Ziel-Schema |
| **Serialize** | Das Ergebnis wird in das Ausgabeformat (XML/JSON) geschrieben |
| **Adapt** | Optional: ein zielsystem-spezifischer Adapter passt die Ausgabe an (z. B. Shopware-Admin-API-Schema) |

Sie sehen diesen Ablauf in der Praxis selten – er läuft intern. Verstehen Sie ihn als Hintergrundinformation: Er erklärt, warum Mapping mal als Direct-Mapping reicht und mal eine Transform-Funktion nötig ist.

## Warum Normalisierung?

Ohne eine kanonische Zwischenform müsste jedes Paar (Eingabeformat × Ausgabeformat) einzeln programmiert werden:

- cXML → openTrans
- cXML → JSON
- Shopware → openTrans
- Shopware → JSON
- EDIFACT → openTrans
- EDIFACT → JSON
- …

Das sind **N × M** Kombinationen. Mit Normalisierung sinkt der Aufwand auf **N + M**: Pro Eingabeformat ein Normalizer, pro Ausgabeformat ein Serializer.

## Was steht im `NormalizedOrder`?

Das Modell ist bewusst klein gehalten. Es deckt ab:

- **Kopf**: Bestellnummer, Datum, Währung, Gesamtbetrag, Typ (`new` / `update` / `delete`)
- **Parteien**: Käufer, Lieferant, Liefer-/Rechnungsadresse
- **Positionen**: Artikelnummer, Bezeichnung, Menge, Mengeneinheit, Einzelpreis
- **Meta**: Empfangszeitpunkt, Pipeline-Name

Alles Weitere (Versandkosten, Steuern, Rabatte, Attribute) lebt in Integrationsspezifischen Feldern und wird über das Feldmapping gezielt gemappt – nicht über den allgemeinen NormalizedOrder.

## Format-Details

### Eingabeformate

Jedes Eingabeformat hat einen eigenen Normalizer:

- **cXML** – parst XML, extrahiert `OrderRequestHeader`, `ShipTo`, `BillTo`, `ItemOut`
- **Shopware 6** – parst JSON aus dem Flow Builder, flacht `orderCustomer`, `deliveries[].shippingOrderAddress`, `lineItems[]` ab
- **Shopify** – liest `order_number`, `shipping_address`, `billing_address`, `line_items`
- **WooCommerce** – liest `number`, `billing`, `shipping`, `line_items`
- **EDIFACT** – parst UNA/UNH/BGM/DTM/NAD/LIN/…-Segmente
- **openTrans** – parst `ORDER_INFO`, `PARTIES`, `ORDER_ITEM_LIST`
- **Generisches JSON** – flacht beliebige JSON-Struktur ab und exponiert alle Felder im Mapping

Siehe die jeweilige Integrations-Seite für Quellfeld-Liste.

### Ausgabeformate

Derzeit sind zwei Hauptformate implementiert:

- **openTrans (XML, Version 2.1)** – passt für klassische ERP- und Warenwirtschafts-Systeme
- **JSON** – passt für moderne REST-APIs und Zielsysteme wie Spryker

Plus das **JTL-Wawi-Auftrags-XML** über einen eigenen Serializer.

## Die Adapter-Stufe

Für manche Zielsysteme reicht „JSON an eine URL schicken" nicht – sie wollen ein sehr spezifisches Datenschema. Hier greift der **Adapter**:

- `passthrough` (Default): Daten unverändert weitergeben
- `shopware6`: Übersetzt generisches JSON in das Shopware-Admin-API-Order-Schema (inklusive Steuer-Kalkulation, UUIDs, State-Machines)
- `spryker`: Übersetzt in JSON:API-Checkout-Schema

Der Adapter ist in der Transport-Config gesetzt und wird **nach** dem Serializer angewendet. Siehe [Shopware 6](/docs/shopware6) und [Spryker](/docs/spryker).

## Was bedeutet das für Ihr Mapping?

- Das Mapping arbeitet auf einem **format-spezifischen Schema**, nicht auf `NormalizedOrder`. Sie sehen im Feldmapping-Editor die Quellfelder wie sie im Ursprungsformat heißen – und die Zielfelder, wie sie das gewählte Ausgabeformat erwartet.
- Orderport nutzt den `NormalizedOrder`-Zwischenschritt intern, um konsistente Defaults liefern zu können und um später neue Formate zu ergänzen, ohne das Mapping-UI umzubauen.
- Wenn eine Auto-Map-Vorschlagsliste ungenügend wirkt, liegt das meist an Lücken im Quell-Normalizer – melden Sie fehlende Feldextraktionen gerne zurück.

## Technische Details

### Reihenfolge der Stufen

Die vier Stufen laufen pro Nachricht immer in dieser Reihenfolge: Normalisierung, Mapping, Serialisierung, optionaler Adapter. Jede Stufe hat ihre eigene Fehlerbehandlung.

### Fehlerbehandlung

- **Normalisierung scheitert** (ungültiges XML, unvollständige JSON-Struktur): Nachricht wird als `failed` markiert, **kein Retry** – das Payload bleibt syntaktisch unlesbar, weitere Versuche würden dasselbe Ergebnis liefern.
- **Serialisierung scheitert** (z. B. fehlendes Pflichtfeld im Mapping): Nachricht wird als `failed` markiert; der Fehler weist meist auf Mapping-Lücken hin und wird durch Anpassung der Regeln behoben.
- **Adapter scheitert** (z. B. Country-Lookup beim Shopware-Adapter läuft in einen Timeout): Nachricht wird als `failed` markiert, aber ein späterer [Retry](/docs/fehlerbehebung) kann erfolgreich sein, weil Live-Lookups in der Zwischenzeit wieder funktionieren.

### Payload-Aufbewahrung

Das Ergebnis der Serialisierung wird zusammen mit dem Rohpayload für 90 Tage aufbewahrt, damit Fehlschläge nachvollzogen werden können. Siehe [Limits & Kontingente](/docs/limits-und-kontingente).

## Nächste Schritte

- [Feldmapping](/docs/feldmapping)
- [Eingangsnachrichten](/docs/inbound-messages)
- [Integrationen-Übersicht](/docs/kategorie/integrationen)
