> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# $wsOrderHistory - Bestellhistorie

> Vergangene Bestellungen eines eingeloggten Kunden im Frontend laden, auflisten und einzelne Bestelldetails anzeigen.

Mit dem `$wsOrderHistory`-Modul lesen Sie die Bestellhistorie des aktuell eingeloggten Kunden und zeigen sie in Ihren Templates an. Damit bauen Sie typische Konto-Funktionen: eine Übersicht aller bisherigen Bestellungen und eine Detailansicht zu einer einzelnen Bestellung (z. B. als Grundlage für eine Nachbestellung).

Da das Modul nur Daten des angemeldeten Kunden liefert, ist außerdem das Zusammenspiel mit dem [Account-Modul](/frontend/referenz/module/wsAccount) relevant.

Auf dieser Seite geht es ausschließlich um den lesenden Zugriff auf bereits abgeschlossene Bestellungen im Template. Der Bestellvorgang selbst ist im [Bestellablauf](/frontend/funktionsubersicht/bestellablauf) beschrieben. Der serverseitige Zugriff auf Bestellungen (z. B. für externe Systeme) erfolgt über die [API-Referenz Bestellungen](/schnittstellen/admin-interface-api/api-referenz-bestellungen), nicht über dieses Modul.

***

## Grundkonzept

`$wsOrderHistory` hat keine eigenen Variablen. Sie rufen eine Methode auf, weisen das Ergebnis einer eigenen [Template-Variable](/frontend/referenz/variablen) zu und arbeiten dann mit dieser weiter. Der typische Ablauf:

1. **Liste laden**: [`loadList()`](#wsorderhistory-loadlist) gibt die Bestellungen des Kunden als Liste zurück. Das Ergebnis weisen Sie z. B. `$orderList` zu.
2. **Prüfen**: Sie prüfen mit `{{ if $orderList }}`, ob überhaupt Bestellungen vorliegen.
3. **Auflisten**: Sie iterieren über die Liste. Pro Eintrag stehen die Eckdaten (`general.orderId`, `general.dateTime`) bereit. Für Summe und Positionen laden Sie die Bestellung über ihre ID nach.
4. **Detail laden**: [`load(orderId)`](#wsorderhistory-load) lädt die vollständige Einzelbestellung (Adressen, Positionen, Preise).

### Nur für eingeloggte Kunden

Beide Methoden liefern nur Daten, wenn ein Kunde angemeldet ist. Ist niemand eingeloggt, erhalten Sie eine leere Rückgabe. Prüfen Sie das Ergebnis deshalb immer mit `{{ if ... }}`, bevor Sie es ausgeben. Sonst entstehen leere Tabellen oder „tote" HTML-Strukturen. Ob ein Kunde angemeldet ist, ermitteln Sie über das [Account-Modul](/frontend/referenz/module/wsAccount).

### Liste und Einzelbestellung im Zusammenspiel

* [`loadList()`](#wsorderhistory-loadlist) liefert die **Übersicht**: eine Liste der Bestellungen. Jeder Eintrag enthält die allgemeinen Eckdaten unter `general`.
* [`load(orderId)`](#wsorderhistory-load) liefert die **Detailansicht** einer einzelnen Bestellung mit allen Daten: Positionen (`orderList.item`), Preise (`order`), Adressen.

Der Übergang von Übersicht zu Detail läuft über die Bestell-ID: In der Liste verlinken Sie jede Bestellung mit der zugehörigen ID, auf der Zielseite lesen Sie diese ID aus dem Aufruf-Parameter und übergeben sie an `load()`. Brauchen Sie schon in der Übersicht Summe oder Positionsanzahl, rufen Sie `load()` auch dort pro Eintrag auf (siehe [Beispiele](#beispiele)).

### Seitenweises Laden (Paging)

Kunden mit langer Historie können sehr viele Bestellungen haben. Statt alle auf einmal zu laden, ruft `loadList()` die Daten über den `options`-Parameter seitenweise ab (Paging). Eine „Seite" ist ein Ausschnitt der Gesamtliste. Sie geben an, welche Seite (`page`) Sie in welcher Größe (`size`) möchten, optional mit einer benannten Sortierung (`sort`). Das hält den Seitenaufbau schlank und ermöglicht eine Blätter-Navigation. Details bei der Methode [`loadList()`](#wsorderhistory-loadlist).

***

## Modulübersicht

**Beispiel / Ausschnitt über** `$wsOrderHistory`

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= $wsOrderHistory | json }}
```

**JSON-Ausgabe**

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "load": "ƒ()",
  "loadList": "ƒ()"
}
```

Anmerkung: `"ƒ()"` kennzeichnet eine Funktion.

**Methoden in der Übersicht**

| **Methode**         | **Rückgabe-Typ** | **Beschreibung**                                                     |
| ------------------- | ---------------- | -------------------------------------------------------------------- |
| `loadList(options)` | array            | Lädt die Bestellungen des Kunden als Liste (seitenweise/sortierbar). |
| `load(orderId)`     | map              | Lädt eine einzelne Bestellung anhand ihrer Bestell-ID.               |

***

## Templates

Die Bestellhistorie lässt sich grundsätzlich in jedem Template laden, wird aber typischerweise im Konto-Bereich des Kunden eingebunden, üblicherweise im Template `account/orderHistory.htm`. Da beide Methoden nur für eingeloggte Kunden Daten liefern (siehe [Grundkonzept](#grundkonzept)), gehört die Ausgabe in einen Bereich, der ohnehin eine Anmeldung voraussetzt.

***

## Variablen

`$wsOrderHistory` stellt keine eigenen Variablen bereit. Die Bestelldaten liegen in der Template-Variable, der Sie das Ergebnis von `loadList()` bzw. `load()` zuweisen (siehe [Grundkonzept](#grundkonzept)).

***

## Methoden

### \$wsOrderHistory.loadList()

Gibt die Bestellungen des aktuell eingeloggten Kunden als Liste zurück, um daraus eine Bestellübersicht zu bauen. Über den optionalen Parameter `options` steuern Sie, welcher Ausschnitt geladen wird: seitenweise (`page`/`size`) und in welcher Sortierung (`sort`).

**Signatur**\
`$wsOrderHistory.loadList(options)`

**Rückgabe**\
`array`. Liste der Bestellungen. Jeder Eintrag trägt unter `general` die Eckdaten (`orderId`, `dateTime`). Leer, wenn kein Kunde eingeloggt ist oder keine Bestellungen vorliegen.

**Parameter**

| **Name**  | **Typ** | **Pflicht** | **Beschreibung**                                                           |
| --------- | ------- | ----------- | -------------------------------------------------------------------------- |
| `options` | map     | nein        | Steuert Paging und Sortierung. Ohne Angabe wird die Standardliste geladen. |

**Optionen (`options`)**

| **Key** | **Typ** | **Pflicht** | **Default** | **Beschreibung**                                                                                |
| ------- | ------- | ----------- | ----------- | ----------------------------------------------------------------------------------------------- |
| `page`  | int     | nein        | `1`         | Welche Ergebnisseite geladen wird. Zählung beginnt bei `1`.                                     |
| `size`  | int     | nein        | -           | Anzahl der Bestellungen pro Seite.                                                              |
| `sort`  | string  | nein        | -           | Name einer in der Konfiguration `general.orderSortOption` definierten Sortierung (siehe unten). |

Über `page` und `size` blättern Sie durch die Historie. So laden Sie die ersten 100 Bestellungen (Seite 1) bzw. die nächsten 100 (Seite 2, also Einträge 101 bis 200):

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $orderList = $wsOrderHistory.loadList({ page: 1, size: 100 }) }}
{{ var $orderListPage2 = $wsOrderHistory.loadList({ page: 2, size: 100 }) }}
```

Das seitenweise Laden hält den Seitenaufbau schlank: Statt die gesamte Historie eines Kunden auf einmal zu verarbeiten, holen Sie nur den Ausschnitt, den die Seite gerade anzeigt.

Pro Eintrag stehen die Eckdaten unter `general` bereit. Für Summe und Positionen laden Sie die Bestellung über `load()` nach (siehe [Beispiele](#beispiele)):

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $orderList = $wsOrderHistory.loadList({ page: 1, size: 100 }) }}
{{ if $orderList }}
  {{ foreach $entry in $orderList }}
    {{= $entry.general.orderId }} – {{= $entry.general.dateTime | dateFmt("%d.%m.%Y") }}
  {{ /foreach }}
{{ /if }}
```

Der Modifier `dateFmt` formatiert den Zeitstempel (ISO-String) in ein lesbares Datum. Der Modifier `date` darf hier nicht verwendet werden. Er bricht das Rendering ab.

**Sortierung über `sort`**

Der Wert von `sort` ist kein freier Feldname, sondern der Name einer vorab definierten Sortier-Option. Diese legen Sie zuerst in der Konfiguration unter [`general.orderSortOption`](/konfiguration/general-allgemeine-shopeinstellungen) an. So sind nur freigegebene, benannte Sortierungen möglich. Das verhindert beliebige Sortierfelder und bündelt die erlaubten Sortierungen zentral.

Eine Sortier-Option hat folgende Felder:

| **Key**     | **Typ** | **Beschreibung**                                                                  |
| ----------- | ------- | --------------------------------------------------------------------------------- |
| `name`      | string  | Eindeutiger Name, den Sie anschließend in `loadList({ sort: "<name>" })` angeben. |
| `fieldName` | string  | Feld, nach dem sortiert wird (z. B. `createdAt`).                                 |
| `direction` | string  | Sortierrichtung: `asc` (aufsteigend) oder `desc` (absteigend).                    |

Beispiel-Konfiguration für „neueste zuerst":

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "direction": "desc",
  "fieldName": "createdAt",
  "name": "dateDesc"
}
```

Anschließend referenzieren Sie diese Sortierung im Template über ihren Namen. Damit liefert `loadList()` die 100 neuesten Bestellungen zuerst:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $orderList = $wsOrderHistory.loadList({ page: 1, size: 100, sort: "dateDesc" }) }}
```

### \$wsOrderHistory.load()

Gibt eine einzelne Bestellung anhand ihrer Bestell-ID als Map mit allen Bestelldaten zurück (z. B. für eine Detailansicht oder eine Nachbestellung).

**Signatur**\
`$wsOrderHistory.load(orderId)`

**Rückgabe**\
`map`- Bestelldaten der angeforderten Bestellung. Leer, wenn kein Kunde eingeloggt ist oder die ID nicht zu einer Bestellung des Kunden gehört.

**Parameter**

| **Name**  | **Typ** | **Pflicht** | **Beschreibung**                            |
| --------- | ------- | ----------- | ------------------------------------------- |
| `orderId` | string  | ja          | ID der Bestellung, die geladen werden soll. |

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $order = $wsOrderHistory.load("48") }}
{{ if $order }}
  Bestellung {{= $order.general.orderId }} vom {{= $order.general.dateTime | dateFmt("%d.%m.%Y") }}
{{ /if }}
```

#### Struktur der Bestell-Map

Die Rückgabe von `load()` ist nach Themen in Unter-Maps gegliedert. Weisen Sie das Ergebnis zunächst einer Variable zu (im Folgenden `$order`) und greifen Sie darüber auf die einzelnen Bereiche zu.

**JSON-Struktur (Überblick):**

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "general":        { "orderId": "...", "dateTime": "...", "shopId": "...", "subshopId": "...", "sessionId": "...", "shopLanguage": "...", "testMode": true },
  "order":          { "priceType": "...", "currencyIso": "...", "currencySymbol": "...", "defaultTaxRate": "...", "paymentId": "...", "paymentOrderText": "...", "delivererId": "...", "delivererOrderText": "...", "deliveryCost": "...", "deliveryTaxRate": "...", "subtotal": "...", "total": "...", "tax": "...", "totalDiscount": "..." },
  "customer":       { "accountType": "...", "accountId": "...", "email": "...", "ipAddress": "..." },
  "orderList":      { "item": [ { "productId": "..." } ] },
  "billAddress":    {},
  "shippingAddress":{},
  "freeFields":     {},
  "deliveryStatus": {}
}
```

`general` enthält die allgemeinen Eckdaten der Bestellung:

| **Key**        | **Typ** | **Beschreibung**                                         |
| -------------- | ------- | -------------------------------------------------------- |
| `orderId`      | string  | ID der Bestellung.                                       |
| `dateTime`     | string  | Datum und Uhrzeit der Bestellung (ISO-String).           |
| `shopId`       | string  | ID des Shops, in dem die Bestellung getätigt wurde.      |
| `subshopId`    | string  | ID des Subshops, in dem die Bestellung aufgegeben wurde. |
| `sessionId`    | string  | ID der Session, in der die Bestellung aufgegeben wurde.  |
| `shopLanguage` | string  | Sprache des Shops zum Bestellzeitpunkt.                  |
| `testMode`     | bool    | `true`, wenn die Bestellung im Testmodus erfolgte.       |

`order` enthält Preise, Zahlungs- und Versandart:

| **Key**              | **Typ** | **Beschreibung**                                   |
| -------------------- | ------- | -------------------------------------------------- |
| `priceType`          | string  | Preistyp: `"net"` (netto) oder `"gross"` (brutto). |
| `currencyIso`        | string  | ISO-Code der Währung (z. B. `"EUR"`).              |
| `currencySymbol`     | string  | Währungssymbol (z. B. `"€"`).                      |
| `defaultTaxRate`     | string  | Standard-Steuersatz.                               |
| `paymentId`          | string  | ID der Zahlungsart.                                |
| `paymentOrderText`   | string  | Beschreibung der Zahlungsart.                      |
| `delivererId`        | string  | ID der Versandart.                                 |
| `delivererOrderText` | string  | Beschreibung der Versandart.                       |
| `deliveryCost`       | string  | Versandkosten.                                     |
| `deliveryTaxRate`    | string  | Steuersatz der Versandkosten.                      |
| `subtotal`           | string  | Warenwert (Summe der Positionen).                  |
| `total`              | string  | Gesamtpreis der Bestellung.                        |
| `tax`                | string  | Gesamte Steuern der Bestellung.                    |
| `totalDiscount`      | string  | Gesamter Rabatt der Bestellung.                    |

`customer` enthält die Daten zum Besteller:

| **Key**       | **Typ** | **Beschreibung**                           |
| ------------- | ------- | ------------------------------------------ |
| `accountType` | string  | Kontotyp: `"Gast"` oder `"Bestandskunde"`. |
| `accountId`   | string  | ID des Accounts.                           |
| `email`       | string  | E-Mail-Adresse des Bestellers.             |
| `ipAddress`   | string  | IP-Adresse zum Bestellzeitpunkt.           |

Weitere Bereiche:

| **Key**           | **Typ** | **Beschreibung**                                                                                                                                                                                                              |
| ----------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `orderList`       | map     | Enthält unter `item` die bestellten Positionen.                                                                                                                                                                               |
| `orderList.item`  | array   | Liste der bestellten Positionen. Jeder Eintrag trägt mindestens `productId` (über [`$wsProducts.load()`](/frontend/referenz/module/wsproducts) ladbar).                                                                       |
| `billAddress`     | map     | Rechnungsadresse.                                                                                                                                                                                                             |
| `shippingAddress` | map     | Lieferadresse.                                                                                                                                                                                                                |
| `freeFields`      | map     | Freie Felder, die bei der Bestellung erfasst wurden.                                                                                                                                                                          |
| `deliveryStatus`  | map     | Lieferstatus der Bestellung (Tracking-Daten oder manueller Statustext). Nur vorhanden, wenn im Admin Interface ein Lieferstatus gesetzt wurde. Details siehe [Lieferstatus (`deliveryStatus`)](#lieferstatus-deliverystatus). |

#### Lieferstatus (`deliveryStatus`)

Der Bereich `deliveryStatus` enthält den Lieferstatus der Bestellung. Er ist nur vorhanden, wenn im Admin Interface ein Lieferstatus für die Bestellung gesetzt wurde. Prüfen Sie das Feld deshalb immer mit `{{ if $order.deliveryStatus }}`, bevor Sie es ausgeben.

Der Lieferstatus wird im Admin Interface unter Bestellungen gepflegt und in zwei Arten unterschieden:

**Geltungsbereich** (`type`):

* `global` - Der Status gilt für die gesamte Bestellung (alle Produkte werden in einem Paket geliefert).
* `splitted` - Die Bestellung wird in mehreren Paketen geliefert; jedes Paket trägt einen eigenen Status und eine Liste der enthaltenen Positionen.

**Status-Art** (bei `global`: `statusType`, bei `splitted` je Paket: `deliveryStatusType`):

* `tracking` - Es wurden eine Sendungsnummer (`trackingNumber`) und ein Versanddienstleister (`trackingVendorId`) hinterlegt. `trackingVendorId` entspricht der `id` der Konfiguration [checkout.shipTrack](/konfiguration/checkout-bestellablauf#checkout-shiptrack-paketverfolgung).
* `manual` - Ein frei formulierter Statustext wurde im Admin Interface eingetragen.

`deliveryStatus` wird nur von [`load()`](#wsorderhistory-load) geliefert. Die Einträge aus [`loadList()`](#wsorderhistory-loadlist) enthalten das Feld nicht - laden Sie die Bestellung bei Bedarf über ihre ID nach.

Struktur bei globalem Status mit Tracking-Daten:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "deliveryStatus": {
    "type": "global",
    "statusType": "tracking",
    "data": {
      "trackingNumber": "5586666654788855",
      "trackingVendorId": "dhl"
    }
  }
}
```

Struktur bei globalem manuellem Status:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "deliveryStatus": {
    "type": "global",
    "statusType": "manual",
    "data": {
      "status": "Wird kommissioniert"
    }
  }
}
```

Struktur bei Lieferung in mehreren Paketen (`splitted`):

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "deliveryStatus": {
    "type": "splitted",
    "packages": [
      {
        "deliveryStatusType": "tracking",
        "data": {
          "trackingNumber": "5586666654788855",
          "trackingVendorId": "dhl"
        },
        "items": [
          {
            "basketId": "62e484ee2283dcab7c14",
            "productId": "237-53337",
            "name": "NextGen X562",
            "quantity": "1.00"
          }
        ]
      }
    ]
  }
}
```

Felder in der Übersicht:

| **Key**                           | **Typ** | **Beschreibung**                                                                                                                      |
| --------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `type`                            | string  | Geltungsbereich des Status: `global` (gesamte Bestellung) oder `splitted` (pro Paket).                                                |
| `statusType`                      | string  | Nur bei `type: "global"`: Art des Status - `tracking` oder `manual`.                                                                  |
| `data`                            | map     | Nur bei `type: "global"`: die Statusdaten (siehe unten).                                                                              |
| `data.trackingNumber`             | string  | Sendungsnummer des Versanddienstleisters (bei `tracking`).                                                                            |
| `data.trackingVendorId`           | string  | ID der [checkout.shipTrack](/konfiguration/checkout-bestellablauf#checkout-shiptrack-paketverfolgung)-Konfiguration (bei `tracking`). |
| `data.status`                     | string  | Manuell eingetragener Statustext (bei `manual`).                                                                                      |
| `packages`                        | array   | Nur bei `type: "splitted"`: Liste der Pakete.                                                                                         |
| `packages[$i].deliveryStatusType` | string  | Art des Status dieses Pakets: `tracking` oder `manual`.                                                                               |
| `packages[$i].data`               | map     | Statusdaten des Pakets (Felder wie oben; bei `manual` heißt das Feld hier `manualStatus`).                                            |
| `packages[$i].items`              | array   | Positionen der Bestellung, die in diesem Paket enthalten sind (u.a. `basketId`, `productId`).                                         |

**Beispiel** \
Lieferstatus einer Bestellung anzeigen. Vor der Anzeige wird über [`$wsShipTrack.zipCodeConfirmed()`](/frontend/referenz/module/wsshiptrack#wsshiptrack-zipcodeconfirmed) geprüft, ob der Kunde die Postleitzahl der Bestellung bestätigt hat; falls nicht, wird das Bestätigungsformular der Aktion `ConfirmZipCode` angezeigt.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $order = $wsOrderHistory.load($wsViews.current.params.orderHistorySelect) }}
{{ if $order.deliveryStatus }}
  {{ if $wsShipTrack.zipCodeConfirmed($order.general.orderId) }}

    {{ if $order.deliveryStatus.type == 'global' }}
      {{# Lieferstatus für die gesamte Bestellung #}}
      {{ if $order.deliveryStatus.statusType == 'manual' }}
        <p><b>Lieferstatus:</b> {{= $order.deliveryStatus.data.status }}</p>
      {{ /if }}
      {{ if $order.deliveryStatus.statusType == 'tracking' }}
        <p><b>Sendungsnummer:</b> {{= $order.deliveryStatus.data.trackingNumber }}</p>
        <p><b>Versanddienstleister:</b> {{= $order.deliveryStatus.data.trackingVendorId }}</p>
      {{ /if }}
    {{ /if }}

    {{ if $order.deliveryStatus.type == 'splitted' }}
      {{# Lieferstatus je Paket #}}
      {{ foreach $package in $order.deliveryStatus.packages }}
        {{ if $package.deliveryStatusType == 'manual' }}
          <p><b>Lieferstatus:</b> {{= $package.data.manualStatus }}</p>
        {{ /if }}
        {{ if $package.deliveryStatusType == 'tracking' }}
          <p><b>Sendungsnummer:</b> {{= $package.data.trackingNumber }}</p>
          <p><b>Versanddienstleister:</b> {{= $package.data.trackingVendorId }}</p>
        {{ /if }}
        {{ foreach $packageItem in $package.items }}
          <p>{{= $packageItem.name }} ({{= $packageItem.quantity }} Stück)</p>
        {{ /foreach }}
      {{ /foreach }}
    {{ /if }}

  {{ else }}
    {{# PLZ noch nicht bestätigt: Formular zur Bestätigung anzeigen #}}
    {{ var $actionConfirmZipCode = $wsActions.create('ConfirmZipCode') }}
    <form method="post" action="{{= $wsViews.current.url() }}">
      <input type="hidden" name="wsact" value="{{= $actionConfirmZipCode.id }}">
      <input type="hidden" name="wscsrf" value="{{= $actionConfirmZipCode.csrf }}">
      <input type="hidden" name="orderId" value="{{= $order.general.orderId }}">
      <p>Bitte bestätigen Sie die Postleitzahl der Lieferadresse, um den Lieferstatus zu sehen:</p>
      <input type="text" name="zipCode">
      <button type="submit">Bestätigen</button>
    </form>
  {{ /if }}
{{ /if }}
```

**Ergebnis**\
Ist der Lieferstatus gesetzt und die Postleitzahl bestätigt, wird je nach Konfiguration der manuelle Statustext oder die Tracking-Information angezeigt - bei Paket-Lieferung pro Paket inklusive der enthaltenen Positionen. Solange die Postleitzahl nicht bestätigt ist, erscheint stattdessen das Bestätigungsformular.

***

## Aktionen

Für `$wsOrderHistory` stehen keine Aktionen zur Verfügung. Für die Bestätigung der Postleitzahl vor Anzeige des Lieferstatus siehe die Aktion `ConfirmZipCode` des Moduls [\$wsShipTrack](/frontend/referenz/module/wsshiptrack).

***

## Beispiele

### Bestellübersicht mit Summe und Positionsanzahl

Lädt die Bestellliste, iteriert über die Einträge und lädt pro Eintrag die vollständige Bestellung nach, um Gesamtpreis (`order.total`) und Anzahl der Positionen (`len(orderList.item)`) anzuzeigen. Jede Zeile verlinkt über `viewUrl()` auf die Detailansicht und hängt die Bestell-ID als Parameter `orderHistorySelect` an.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $orderList = $wsOrderHistory.loadList() }}
{{ if $orderList }}
  {{ foreach $entry in $orderList }}
    {{ var $order = $wsOrderHistory.load($entry.general.orderId) }}
    {{ if $order }}
      <a href="{{= $wsViews.viewUrl('account/orderHistory.htm', { wsvc: 'View', orderHistorySelect: $entry.general.orderId }) }}">
        <strong>{{= $entry.general.dateTime | dateFmt("%d.%m.%Y") }}</strong>
        – {{= len($order.orderList.item) }} Position(en)
        – {{= $order.order.total | currency }}
      </a>
    {{ /if }}
  {{ /foreach }}
{{ else }}
  <p>Es liegen keine Bestellungen vor.</p>
{{ /if }}
```

**Ergebnis** \
Pro Bestellung eine verlinkte Zeile mit Datum, Positionsanzahl und Gesamtpreis. Der Modifier `currency` gibt das Währungssymbol bereits mit aus (kein separates `currencySymbol` nötig). Ist der Kunde nicht eingeloggt oder hat keine Bestellungen, erscheint der Hinweistext.

### Eine Bestellung aus der Liste öffnen (Detailansicht)

Schließt den Loop: Die Detailansicht liest die in der Übersicht angehängte Bestell-ID aus dem URL-Parameter, lädt damit die Einzelbestellung und gibt deren Eckdaten samt Positionen aus.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsViews.current.params.orderHistorySelect }}
  {{ var $order = $wsOrderHistory.load($wsViews.current.params.orderHistorySelect) }}
  {{ if $order }}
    <h2>Bestellung {{= $order.general.orderId }}</h2>
    <p>Datum: {{= $order.general.dateTime | dateFmt("%d.%m.%Y") }}</p>
    <p>Gesamtpreis: {{= $order.order.total | currency }}</p>
    <p>Zahlungsart: {{= $order.order.paymentOrderText }}</p>
    <p>Versandart: {{= $order.order.delivererOrderText }}</p>

    {{ foreach $position in $order.orderList.item }}
      {{ var $product = $wsProducts.load($position.productId) }}
      {{ if $product }}
        <p>{{= $product.name }}</p>
      {{ /if }}
    {{ /foreach }}
  {{ /if }}
{{ /if }}
```

**Ergebnis** \
Klickt der Kunde in der Übersicht auf eine Bestellung, wird die Seite mit `?wsvc=View&orderHistorySelect=<ID>` neu aufgebaut, die Bestellung geladen und mit ihren Positionen angezeigt. Jede Position wird über ihre `productId` mit `$wsProducts.load()` zum vollständigen Produkt aufgelöst.

### Seitenweise durch viele Bestellungen blättern

Über `page` blättern Sie durch lange Historien. Die anzuzeigende Seitennummer holen Sie aus einem URL-Parameter, sodass ein „Weiter"-Link jeweils einen neuen Seitenaufbau mit der nächsten Seite auslöst.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $page = $wsViews.current.params.orderPage }}
{{ if not $page }}{{ var $page = 1 }}{{ /if }}

{{ var $orderList = $wsOrderHistory.loadList({ page: $page, size: 20 }) }}
{{ if $orderList }}
  {{ foreach $entry in $orderList }}
    <p>{{= $entry.general.orderId }} – {{= $entry.general.dateTime | dateFmt("%d.%m.%Y") }}</p>
  {{ /foreach }}
  <a href="{{= $wsViews.viewUrl('account/orderHistory.htm', { wsvc: 'View', orderPage: $page + 1 }) }}">Nächste Seite</a>
{{ /if }}
```

**Ergebnis** \
Pro Seitenaufruf werden 20 Bestellungen angezeigt. Der Link lädt jeweils die nächsten 20.

### Nach Datum sortieren (neueste zuerst)

Setzt die in der Konfiguration `general.orderSortOption` angelegte Sortier-Option `dateDesc` voraus (siehe [`loadList()`](#wsorderhistory-loadlist)). Damit liefert `loadList()` die neuesten Bestellungen zuerst.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $orderList = $wsOrderHistory.loadList({ page: 1, size: 100, sort: "dateDesc" }) }}
{{ if $orderList }}
  {{ foreach $entry in $orderList }}
    <p>{{= $entry.general.dateTime | dateFmt("%d.%m.%Y") }} – {{= $entry.general.orderId }}</p>
  {{ /foreach }}
{{ /if }}
```

**Ergebnis** \
Die 100 neuesten Bestellungen, absteigend nach Bestelldatum sortiert.

***

## Weiterführende Links

* [\$wsAccount - Account & Adressdaten](/frontend/referenz/module/wsAccount): um zu prüfen, ob ein Kunde eingeloggt ist, bevor Sie die Historie laden.
* [\$wsViews - Aktuelle Informationen abrufen](/frontend/referenz/module/wsviews): liefert `viewUrl()` für die Detail-Verlinkung und `current.params` zum Auslesen des Parameters `orderHistorySelect`.
* [\$wsProducts - Produktdaten](/frontend/referenz/module/wsproducts): lädt zu einer `productId` aus `orderList.item` das vollständige Produkt (Name, Bilder).
* [\$wsShipTrack - Sendungsverfolgung](/frontend/referenz/module/wsshiptrack): lädt zu einer Sendungsnummer aus `deliveryStatus` die Tracking-Informationen des Versanddienstleisters und prüft die PLZ-Bestätigung.
* [general - Allgemeine Shopeinstellungen](/konfiguration/general-allgemeine-shopeinstellungen): hier soll unter `orderSortOption` die für `sort` vorgesehene Sortier-Option angelegt werden (siehe Hinweis bei `loadList()`).
* [Bestellablauf](/frontend/funktionsubersicht/bestellablauf): beschreibt, wie eine Bestellung entsteht (Abgrenzung zu dieser Seite).
