{{= $myProduct.description }}
``` Die Template Engine interpretiert diese Platzhalter und ersetzt sie zur Laufzeit mit den entsprechenden Werten aus dem System. ### Standard-Escaping Die WEBSALE Template-Engine verfügt über ein integriertes Standard-Escaping, das automatisch auf alle dynamisch eingebundenen Inhalte angewendet wird. Dadurch wird sichergestellt, dass HTML- oder JavaScript-Code, der z. B. in Produktdaten oder CMS-Inhalten enthalten ist, nicht interpretiert, sondern als Klartext dargestellt wird. Viele Inhalte im Shop – z. B. Produktbeschreibungen, CMS-Artikel oder andere redaktionelle Texte – enthalten HTML zur Formatierung. Damit diese Inhalte nicht unbeabsichtigt als echter HTML-Code ausgeführt werden, wird bei der Ausgabe mit `{{= ... }}` ein automatisches Escaping angewendet. **Beispiel: Standard-Escaping aktiviert** ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{= $product.description }} ``` **Inhalt in den Shopdaten:** ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}Super atmungsaktiv – ideal für Sport und Freizeit. Jetzt in der neuesten Generation erhältlich.
``` **Ausgabe im Browser:** ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} <p><strong>Super atmungsaktiv</strong> – ideal für Sport und Freizeit. Jetzt in der <em>neuesten Generation</em> erhältlich.</p> ``` Der HTML-Code wird **nicht interpretiert**, sondern als normaler Text angezeigt. Das schützt vor unbeabsichtigter Codeausführung. Wenn Inhalte bewusst als HTML ausgegeben werden sollen – z. B. weil Produkttexte oder CMS-Inhalte HTML enthalten und korrekt gerendert werden sollen – kann das Escaping gezielt deaktiviert werden. Dazu wird statt `=` ein Ausrufezeichen `!` verwendet: ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{! $product.description }} ``` **Ausgabe im Browser:** ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}Super atmungsaktiv – ideal für Sport und Freizeit. Jetzt in der neuesten Generation erhältlich.
``` Jetzt wird der HTML-Code korrekt interpretiert und gerendert. **Wichtig:** Die Deaktivierung des Escapings sollte nur bei vertrauenswürdigen Inhalten erfolgen – z. B. bei Daten aus dem eigenen Produkt-Backend oder CMS. Inhalte, die z. B. über Formulareingaben von Kunden stammen, sollten nicht ungefiltert ohne Escaping ausgegeben werden. *** ## Variablen Mit der WEBSALE Template-Sprache können die Daten ausgegeben werden, die vom Shopsystem bereitgestellt werden. Jede Seite, die von der Template Engine gerendert wird, erhält so die benötigten Daten, um die angeforderten Inhalte anzuzeigen. Diese Daten werden in sogenannten Template-Variablen gespeichert. Alle Template-Variablen können über die Template-Sprache mit einem `$` gefolgt vom Variablennamen aufgerufen werden. Variablennamen können frei vergeben werden. Es gibt auch Systemvariablen, die mit `$ws` beginnen und deren Namen vorgegeben sind. Beispiele hierfür sind die Module `$wsProducts` und `$wsCategories`. Eine vollständige Übersicht der WEBSALE Systemvariablen und weitere Informationen zu den Variablen allgemein finden Sie in der [Übersicht der Variablen](/frontend/referenz/variablen). ### Variablen setzen & verwenden **Beispiel: Neue Variable** ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{ var $myProduct = $wsProducts.load('1234') }} ``` Neue Variablen werden immer mit dem **var-Keyword** definiert. In diesem Beispiel lädt die Funktion [`$wsProducts.load('1234')`](/frontend/referenz/module/wsproducts) die Daten des Produkts mit der Produkt-ID `1234`. Diese werden in der Variable `$myProduct` gespeichert und können später verwendet werden. **Beispiel: Verwendung der Variablen** ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{ var $myProduct = $wsProducts.load('1234') }}{{= $myProduct.description }}
Preis: {{= $myProduct.price }} €
``` Einmal definierte Variablen können an beliebigen Stellen im Template genutzt werden. In diesem Fall: * Die Produktdaten werden in `$myProduct` gespeichert. * Der Produktname, die Beschreibung und der Preis werden dynamisch in das Template eingefügt. **Beispiel: Verschachtelte Variable** ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{ var $myProduct = $wsProducts.load('1234') }}Diese Kategorie ist aktiv.
{{ /if }} ``` Variablen, die innerhalb von Bereichsanweisungen definiert werden, existieren nur innerhalb dieses Bereichs: ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{ foreach $myProduct in $wsCategories.loadProducts('5678') }}{{= $myProduct.price }} €
{{ /foreach }}{{= $myProduct.name }}
-> $myProduct ist außerhalb der Schleife nicht gültig ``` *** ## Modifiers (Modifikatoren) Manchmal reicht es nicht aus, den Inhalt einer Variable einfach nur auszugeben. Der Wert muss zuvor verändert oder angepasst werden. Genau dafür gibt es die sogenannten **Modifiers**. **Modifiers** können auf alle Variablen angewendet werden, um deren Inhalt zu verändern. Dazu fügen Sie der entsprechenden Variable ein `|` (Pipe-Zeichen) und den Modifiernamen hinzu. Zusätzliche Parameter werden in runden Klammern angegeben. **Beispiel: Kürzen eines Textes** ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{= $myProduct.name | take(30) }} ``` In diesem Beispiel wird der Modifier [`take`](/frontend/referenz/funktionen#take) auf den Produktnamen angewendet. Er gibt nur die ersten 30 Zeichen aus. **Beispiel: Mehrere Modifiers auf eine Variable anwenden** Sie können auch mehrere Modifiers hintereinander auf eine Variable anwenden. Sie werden in der angegebenen Reihenfolge verarbeitet. ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{= $myProduct.description | stripHtml | take(120) }} ``` Hier entfernt [`stripHtml`](/frontend/referenz/funktionen#striphtml) zunächst die HTML-Formatierungen aus der Produktbeschreibung. Anschließend kürzt `take` den reinen Text auf 120 Zeichen. Eine vollständige Liste aller Modifiers sowie deren Beschreibung finden Sie in der [Übersicht der Modifikatoren.](/frontend/referenz/modifiers) *** ## Bedingungen (Conditions) Mithilfe von Bedingungen können Sie die Ausgabe in der Storefront abhängig von bestimmten Werten variieren. Eine Bedingung wird mit `{{ if }}` eingeleitet und mit `{{ /if }}` abgeschlossen. Dazwischen sind beliebig viele `{{ elseif }}`-Zweige und ein `{{ else }}`-Zweig erlaubt. Der Inhalt eines Zweigs wird nur ausgegeben, wenn die Prüfung darin wahr (`true`) ist. **Beispiel:** ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{ if $myProduct.description }} {{= $myProduct.description }} {{ else }} {{= $myProduct.custom.shortdescr }} {{ /if }} ``` In diesem Beispiel wird geprüft, ob die Variable `$myProduct.description` einen Inhalt hat. Wenn ja, wird ihr Inhalt ausgegeben. Andernfalls wird der alternative Inhalt im **else**-Zweig ausgegeben, hier eine Kurzbeschreibung aus einem Produktdatenfeld. Zusätzlich zu `if` und `else` können auch mehrere Prüfungen hintereinander definiert werden, indem `{{ elseif }}` hinzugefügt wird. **Beispiel: Begrüßung des Besuchers im Onlineshop** * Ist ein Kunde eingeloggt und hat er eine Rechnungsadresse hinterlegt, wird er mit seinem Vornamen begrüßt. * Ist ein Kunde eingeloggt, aber ohne hinterlegte Rechnungsadresse, wird eine allgemeine Begrüßung angezeigt. * Für alle nicht eingeloggten Besucher wird ein Hinweis zur Registrierung angezeigt. ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{ if $wsAccount.isLoggedIn and $wsAccount.defaultBillAddress.firstName }}Willkommen zurück, {{= $wsAccount.defaultBillAddress.firstName }}!
{{ elseif $wsAccount.isLoggedIn }}Willkommen zurück!
{{ else }}Willkommen! Registrieren Sie sich.
{{ /if }} ``` **Beispiel: Bedingungen mit Operatoren, beispielsweise für den Lagerbestand** Mit Operatoren lassen sich auch Werte vergleichen, beispielsweise mit `>` oder `<` die verfügbare Stückzahl eines Produktes. Die Bestandsdaten liefert das Modul [`$wsInventory`](/frontend/referenz/module/wsinventory): ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} {{ var $myInventory = $wsInventory.load($myProduct.id) }} {{ if $myInventory.amount > 0 }}Dieses Produkt ist verfügbar.
{{ else }}Dieses Produkt ist nicht verfügbar.
{{ /if }} ``` Eine vollständige Übersicht der verfügbaren Operatoren und deren Verwendung finden Sie in der [Referenz der Operatoren](/frontend/referenz/operatoren). *** ## Loops (Schleifen) Schleifen ermöglichen es, durch eine Liste mit mehreren Datensätzen, beispielsweise Produkten, zu iterieren und automatisch Inhalte für jeden einzelnen Datensatz zu erzeugen. So können Sie wiederkehrende Strukturen wie Produktlisten oder Bildergalerien effizient erstellen. Eine Schleife wird mit `{{ foreach{{= $myProduct.description }}
Preis: {{= $myProduct.price }} €
Keine Produkte in dieser Kategorie verfügbar.
{{ /if }}
```
***
## Basis-Template (Layout-Template)
Das Basis-Template, auch als **Layout-Template** bezeichnet, legt das allgemeine Grundgerüst für alle Seiten der Storefront fest. Es definiert zentrale Inhalte und Bereiche, die auf den meisten Shopseiten wiederverwendet werden, und sorgt so für eine einheitliche Struktur und Benutzerführung.
Das Layout-Template ist keine eigenständige Shopseite und kann nicht direkt von außen per Link aufgerufen werden. Es wird stattdessen von den spezifischen [Seiten-Templates (Views) ](#view-templates-seiten-templates)erweitert oder eingebunden.
Das Basis-Template befindet sich im Verzeichnis
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
templates
├── layouts
```
Hier können ein oder mehrere Layout-Templates abgelegt werden, je nach Anwendungsfall (z. B. allgemeines Layout, Kundekonto, Checkout-spezifisches Layout, Mails etc.)
Das Layout-Template enthält üblicherweise die folgenden zentralen Elemente:
* **Technischer** ``**-Bereich:**
* Meta-Angaben für Suchmaschinenoptimierung (z. B. Title, Description, Keywords).
* Verweise auf die CSS- und JavaScript-Dateien der Storefront.
* Integration von externen Ressourcen wie Schriftarten oder Tracking-Codes.
* **Sichtbarer Headerbereich:**
* Logo: Darstellung des Shop-Logos.
* Suche: Eingabefeld für die Produktsuche.
* Login-Bereich: Zugriff auf das Kundenkonto.
* Warenkorb und Merkliste: Übersicht über gespeicherte Produkte.
* Navigation: Primäre Navigation des Shops (z. B. Kategorien).
* **Breadcrumb:**
* Anzeige des aktuellen Navigationspfads zur besseren Orientierung der Benutzer.
* **Footer:**
* Weiterführende Verlinkungen wie Impressum, Datenschutz, AGB.
* Kontaktinformationen oder andere zusätzliche Inhalte.
Ein Layout-Template wird in den [Seiten-Templates (Views)](#view-templates-seiten-templates) über den `extends`**-Befehl** eingebunden:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ extends "layouts/default.htm" }}
```
***
## Template-Blöcke
Template-Blöcke bilden die grundlegende Struktur eines Basis-Templates und ermöglichen eine einfache und flexible Anpassung der Storefront. Sie gruppieren die Storefront-Komponenten in kleine, isolierte Blöcke, die unabhängig voneinander bearbeitet oder überschrieben werden können. Dieses Block-System sorgt für eine saubere Struktur und Wiederverwendbarkeit von Inhalten.
Template-Blöcke sind klar definierte Bereiche innerhalb eines Templates, die durch das `block`-Element gekennzeichnet sind. Sie dienen dazu, einzelne Komponenten der Storefront (z. B. Header, Footer, Navigation) voneinander zu trennen, sodass jede Komponente unabhängig angepasst werden kann.
**Beispiel eines Blocks:**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ block header }}
Das ist unser spezieller Header für die Startseite.
Versandkostenfreiheit ab 50.00 € Einkaufswert
{{ /block }} ``` Mehr Informationen zu den Template-Blöcken sowie deren Verwendung und Anpassung finden sich in der [Referenzdokumentation zu Template-Blöcken](/frontend/referenz/blocke). *** ## View-Templates (Seiten-Templates) View-Templates definieren die individuellen Inhalte für spezifische Shopseiten und sind die einzigen Templates, die von außen per Link adressierbar sind. Sie basieren in der Regel auf einem Basis-Template und verwenden dessen Blöcke, um eine konsistente Struktur und Gestaltung beizubehalten. View-Templates befinden sich im Verzeichnis ```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} templates ├── views ``` View-Templates können direkt verlinkt werden, indem ihre URL über den folgenden Befehl generiert wird: ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}} Impressum ``` In diesem Beispiel wird auf das View-Template `impressum.htm` verlinkt. #### Direkter URL-Aufruf eines View-Templates Intern erzeugt `$wsViews.viewUrl()` eine URL mit den Query-Parametern `wsvc=View` und `view=| Produkt | Menge | Preis | |
|---|---|---|---|
|
|
{{ if $cItem.product.custom.brand }}
{{= $cItem.product.custom.brand }} {{ /if }} {{= $cItem.product.name }} {{ foreach $cVarAttr in $cItem.product.variantSelection | keys }} {{= $cVarAttr }}: {{= $cItem.product.variantSelection[$cVarAttr] }} {{ /foreach }} |
{{= $cItem.quantity | preparedFormat('amount') }} | {{= $cItem.total | currency }} |
| Zwischensumme | {{= $wsBasket.subTotal | currency }} |
| Versandkosten | {{= $wsBasket.shippingCosts | currency }} |
| Gesamtsumme |
Vielen Dank für Ihre Bestellung.
Nur „{{= $compareType }}" vergleichbar
{{ elseif $maxReached }}Max. Produkte im Vergleich erreicht
{{ else }} {{ var $addIds = [] }} {{ foreach $id in $compareIds }} {{ push($addIds, $id) }} {{ /foreach }} {{ push($addIds, $cProduct.id) }} {{ var $addIdsStr = join($addIds, ",") }} {{ var $addTypeStr = $compareType }} {{ if $addTypeStr == "" }} {{ $addTypeStr = $productCategory }} {{ /if }} {{ /if }}`
* an einer SEO-URL des Produkts: `/buntes-t-shirt?insert=`
* **Direktbestellung**: Der Kunde gibt die Artikelnummer zusammen mit dem Werbemittelkennzeichen in ein einziges Feld ein, so wie sie im Katalog abgedruckt ist, beispielsweise `123456/AB`. Der Shop trennt den Code selbst ab. Wie das funktioniert, steht unter [Werbemittelkennzeichen in der Direktbestellung erfassen](#werbemittelkennzeichen-in-der-direktbestellung-erfassen).
* **Warenkorb (Schnittstelle)**: Beim Hinzufügen oder Ändern eines Postens kann der Code direkt mitgegeben werden, siehe [Storefront-API Warenkorb](/schnittstellen/storefront-api/storefront-api-warenkorb).
Eine View-URL ist dabei eine über die Template-Funktion `$wsViews.url(...)` beziehungsweise `$wsViews.viewUrl(...)` erzeugte, technische Shop-URL (im Gegensatz zur sprechenden SEO-URL). Details siehe [Modul \$wsViews](/frontend/referenz/module/wsviews). Beide URL-Arten nehmen den `insert`-Parameter gleichermaßen an.
Wird ein Produkt **ohne** `insert`-Parameter aufgerufen, bleibt ein für dieses Produkt bereits gemerktes Werbemittelkennzeichen erhalten. „Kein Parameter" wird also nicht wie „kein Code" behandelt. Der gemerkte Code wird erst beim Hinzufügen des Produkts in den Warenkorb herangezogen und dort gegen die gültigen Codes geprüft.
## Praxisbeispiel: von der Anzeige bis zur Bestellung
Das folgende Szenario veranschaulicht, wie die Regeln zusammenspielen:
Ein Kunde erhält ein Mailing mit einem Produktlink, an den das Werbemittelkennzeichen `09` angehängt ist (beispielsweise `/buntes-t-shirt?insert=09`). Mit einem Klick gelangt er auf die Produktseite. Der Shop merkt sich den Code `09` für das T-Shirt.
Anschließend legt er das T-Shirt in den Warenkorb. Da `09` für dieses Produkt ein gültiger Code ist, trägt die Position das Kennzeichen und die Artikelnummer erscheint als `123456-09`.
Danach stöbert er weiter, legt eine Hose in den Warenkorb und ruft dabei keinen Code auf. Der Code `09` gehört zum T-Shirt und wird nicht auf die Hose übertragen. Für die Hose gilt entweder der Standardcode oder die Position bleibt ohne Kennzeichnung.
Später ruft er über einen zweiten Link aus einer Anzeige eine Jacke mit dem Code `DA` auf und legt sie in den Warenkorb. Im Warenkorb liegen nun drei Artikel: das T-Shirt mit der Nummer `09`, die Hose ohne Code und die Jacke mit dem Code `DA`.
Beim Abschluss der Bestellung wird das Kennzeichen jeder Position zusammen mit der Bestellung gespeichert. Anschließend beginnt eine neue Sitzung, und die gemerkten Codes entfallen.
In der Bestellhistorie steht das gespeicherte Kennzeichen in den Bestelldaten (im Feld `insert`). Eine fertig zusammengesetzte Anzeige aus Artikelnummer und Code liefert der Shop weder dort noch im Warenkorb. Wie sich das Kennzeichen in der Bestellhistorie darstellen lässt, ist unter [Beispiele → Bestellhistorie](#bestellhistorie) beschrieben.
## Sonderfälle
**Set-Artikel:** Der Code wird sowohl für die Hauptposition als auch für die enthaltenen Unterartikel aufgelöst. Jeder Unterartikel prüft den Code gegen seine eigenen gültigen Codes (sonst greift der Standardcode). Das funktioniert genauso wie bei einem einzeln hinzugefügten Artikel.
**Varianten:** Die zulässigen Codes werden auf Ebene des Hauptprodukts gepflegt und gelten für alle seine Varianten. Gemerkt wird der Code dagegen je Variante. Wechselt der Kunde auf der Produktdetailseite die Variante, gilt für die neue Variante deren eigenes, bereits gespeichertes Kennzeichen. Der Shop übernimmt den Code der zuvor gewählten Variante nicht. Der Code wird immer gegen die gültigen Codes des Hauptprodukts geprüft.
## Einrichtung
Dieser Abschnitt beschreibt die konkreten Schritte zu den unter [Voraussetzungen](#voraussetzungen) genannten Bedingungen.
### Konfiguration
Die Einstellungen liegen im Konfigurationsbereich unter (`content.inserts`):
| **Einstellung** | **Bedeutung** | **Standard** |
| - | - | - |
| `enabled` | Schaltet die gesamte Funktion ein beziehungsweise aus. | aus |
| `defaultInsertCode` | Wird verwendet, wenn kein oder ein ungültiger Code erfasst wurde. Leer lassen, wenn in diesem Fall gar kein Kennzeichen gesetzt werden soll. | leer |
| `separator` | Zeichen zwischen Produktnummer und Code, beispielsweise `-`. | `-` |
| `position` | Steht der Code hinter der Produktnummer (`123456-09`) oder davor (`09-123456`). | dahinter |
| `insertCodeLength` | Feste Zeichenanzahl des Werbemittelkennzeichens. Wird nur benötigt, wenn kein Trennzeichen gesetzt ist. Dann lassen sich Nummer und Code in der Direktbestellung nur über die feste Länge trennen. Mit gesetztem Trennzeichen hat der Wert keine Bedeutung. | `0` |
Solange `enabled` deaktiviert ist, bleibt die Funktion im gesamten Shop wirkungslos, unabhängig davon, wie die einzelnen Produkte gepflegt sind.
Wenn der Shop ohne Trennzeichen mit `insertCodeLength` arbeitet, müssen alle Werbemittelkennzeichen im Shop dieselbe Länge haben. Ein Code mit abweichender Länge wird bei der Direktbestellung falsch abgetrennt.
Hinweis zu `defaultInsertCode`: Der Standardcode greift produktübergreifend für jede Eingabe, die nicht zu einem gültigen Code aufgelöst werden kann. Wer den Code auf einen festen Wert setzt, sollte bedenken, dass dieser Wert dann auch für Posten verwendet werden kann, für die eigentlich kein Werbemittelkennzeichen vorgesehen ist. Im Zweifel sollten Sie den Wert leer lassen.
### Produktfeld anlegen
Ist das Feld `validInsertCodes` im Shop noch nicht vorhanden, wird es einmalig als benutzerdefiniertes Produktfeld angelegt. Im Admin Interface geschieht das im Bereich Katalog → Produkte über die Produktfelder-Einstellungen (Einstellungen / Zahnrad rechts oben anwählen). Die dortige Tabelle zeigt alle vorhandenen Produktfelder mit Name, Typ und maximaler Länge. Über die Schaltfläche **Neu** wird das Feld mit folgenden Einstellungen angelegt:
| **Einstellung** | **Wert** |
| - | - |
| Name | `validInsertCodes` |
| Label | Gültige Werbemittelkennzeichen |
| Typ | Liste (Texteinträge) |
| Maximale Länge | 16 Zeichen je Eintrag |
Alternativ kann das Feld über die [REST API Konfiguration](/schnittstellen/admin-interface-api/api-referenz-konfiguration) im Knoten `content.customProductField` erstellt werden.
### Feldzuordnung einrichten
Nach dem Anlegen des Produktfelds muss es einmalig der Funktion zugeordnet werden. Erst durch diese Zuordnung weiß der Shop, in welchem Produktfeld die gültigen Werbemittelkennzeichen stehen.
Die Zuordnung wird im Konfigurationsknoten [content.usedFields](/konfiguration/content-katalog-kategorien-produkte#content-usedfields-zuordnung-benutzerdefinierter-felder) gepflegt. Im Bereich `products` verweist der Eintrag `validInsertCodes` auf das angelegte Produktfeld:
```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
"products": {
"validInsertCodes": "content.customProductField.validInsertCodes"
}
}
```
Das Beispiel zeigt nur den relevanten Eintrag. Der Knoten enthält daneben die Zuordnungen aller anderen Funktionsbereiche (beispielsweise `weight`, `crossSelling`, `metaTitle`). Diese bestehenden Einträge bleiben unverändert erhalten, es wird ausschließlich der Wert von `validInsertCodes` gesetzt.
Ohne diese Zuordnung wirken die am Produkt gepflegten Codes nicht. Der Shop kann die gültigen Codes eines Produkts dann nicht ermitteln, und jeder Posten erhält stillschweigend den Standardcode oder bleibt ohne Kennzeichen, auch wenn an den Produkten Codes gepflegt sind. Es reicht also nicht, das Produktfeld nur anzulegen, es muss auch zugeordnet werden.
### Zulässige Codes am Produkt
Das benutzerdefinierte Produktfeld „Gültige Werbemittelkennzeichen“ (`validInsertCodes`) wird im Admin-Interface auf der Detailseite des jeweiligen Produkts gepflegt. Wie jedes benutzerdefinierte Feld erscheint es in der entsprechenden Feldgruppe. Andernfalls erscheint es in der Sammelgruppe „Sonstige”. Über dieses Feld wird pro Produkt festgelegt, welche Codes für dieses Produkt erlaubt sind.
Es handelt sich um ein Listenfeld. Jeder gültige Code wird als eigener Eintrag erfasst. Ein Trennzeichen wird nicht benötigt und die Codes werden nicht als zusammenhängende Zeichenkette gepflegt. Folgende Voraussetzungen gelten für das Anlegen eines Codes:
* Jeder Eintrag darf maximal 16 Zeichen lang sein.
* Jeder Code ist ein eigener Listeneintrag. Die Codes werden nicht durch Kommas oder andere Trennzeichen in einem Feld aneinandergereiht.
* Die Codes sind case-sensitiv (beispielsweise ist `DA` nicht gleich `da`).
* Das Feld wird auf Ebene des Hauptprodukts gepflegt und gilt für dessen Varianten mit.
* Ist die Liste leer, kann für dieses Produkt kein Code übernommen werden (es greift höchstens der [Standardcode](#konfiguration), sofern gesetzt).
Im Template steht das Feld als Liste zur Verfügung, beispielsweise über `$cProduct.custom.validInsertCodes` auf der Produktseite oder `$item.product.custom.validInsertCodes` an der Warenkorbposition. Die Ausgabe erfolgt per Schleife oder mit `join` und frei wählbarem Trennzeichen:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= $cProduct.custom.validInsertCodes | join(", ") }}
```
**Ergebnis**
Die gültigen Codes des Produkts werden kommagetrennt angezeigt, beispielsweise `DA, 09`.
## Anzeige im Shop
Das Werbemittelkennzeichen kann als Teil der Artikelnummer im Warenkorb, in der Bestellübersicht, in der Bestätigungs-E-Mail, im Bestell-PDF sowie in der Bestellhistorie angezeigt werden (beispielsweise `123456-09`). Dabei gelten die konfigurierte Reihenfolge und das konfigurierte Trennzeichen. Voraussetzung ist, dass die Ausgabe im jeweiligen Template eingebunden ist (siehe [Beispiele](#beispiele)).
Die Anzeige setzt sich aus der Artikelnummer der Position (`$item.itemNumber`) und dem Code (`$item.insert`) zusammen. Bei Varianten entspricht`$item.itemNumber` der Nummer der bestellten Variante. Für das Zusammensetzen gibt es die wiederverwendbare Komponente `components/itemNumberWithInsert.htm`. Sie gibt je nach Konfiguration `CodeNummer` oder `NummerCode` aus. Ist der Code leer, gibt sie nur die Nummer aus.
Mithilfe des Moduls [\$wsInserts](/frontend/referenz/module/wsinserts) kann ein gemerktes Kennzeichen auch außerhalb des Warenkorbs angezeigt werden, beispielsweise auf Kategorie-Kacheln und der Produktdetailseite.
Wird ein unbekannter Code eingegeben, verwirft der Shop diesen und greift, sofern eingerichtet, auf den Standardwert zurück. Dadurch wird die Bestellung nie blockiert.
## Module
Für die Ausgabe des Werbemittelkennzeichens im Template werden diese Module verwendet:
* [\$wsInserts](/frontend/referenz/module/wsinserts) liefert das je Produkt gemerkte Kennzeichen über `$wsInserts.byProduct` sowie die Einstellungen (aktiv, Trennzeichen, Position, Standardcode). Damit lässt sich das Kennzeichen überall anzeigen, wo ein Produkt dargestellt wird.
* [\$wsBasket](/frontend/referenz/module/wsbasket) liefert je Warenkorbposition das Kennzeichen über `$item.insert` und die Artikelnummer der Position über `$item.itemNumber`.
* [\$wsConfig](/frontend/referenz/module/wsconfig) liefert über `$wsConfig.inserts` dieselben Einstellungen wie `$wsInserts`. Das Objekt bleibt weiterhin verfügbar.
Die Erfassung eines Codes (URL, Direktbestellung, Warenkorb-Schnittstelle) benötigt kein eigenes Modul. Sie geschieht über URL-Parameter, das Direktbestellformular oder die [Storefront-API](/schnittstellen/storefront-api/storefront-api-warenkorb).
## Beispiele
### Artikelnummer mit Werbemittelkennzeichen ausgeben
Im Warenkorb (und analog dazu in der Bestellübersicht, der E-Mail und dem PDF) übergeben Sie der Komponente `components/itemNumberWithInsert.htm` die Artikelnummer und den Code der Position. Die Reihenfolge und die Trennzeichen werden von der Komponente selbst berücksichtigt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $item in $wsBasket.items }}
Art.-Nr.: {{ include "components/itemNumberWithInsert.htm" with $cNumber = $item.itemNumber, $cCode = $item.insert }}
Produktname: {{= $item.product.name }}
{{ /foreach }}
```
**Ergebnis**
Jede Position zeigt ihre Artikelnummer inklusive Werbemittelkennzeichen, sofern eines erfasst wurde. Andernfalls wird die reine Artikelnummer angezeigt.
### Gemerktes Werbemittelkennzeichen am Produkt anzeigen
Auf einer Kategorie-Kachel oder der Produktdetailseite liefert `$wsInserts.byProduct` den für das Produkt gemerkten Code. Ist für das Produkt kein gültiger Code gemerkt, bleibt der Wert leer.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsInserts.enabled and $wsInserts.byProduct[$cProduct.id] }}
Art.-Nr.: {{ include "components/itemNumberWithInsert.htm" with $cNumber = $cProduct.itemNumber, $cCode = $wsInserts.byProduct[$cProduct.id] }}
{{ /if }}
```
**Ergebnis**
Hat der Kunde das Produkt über einen Link mit Werbemittelkennzeichen aufgerufen, erscheint die Artikelnummer mit diesem Code. Andernfalls erscheint nichts.
### Werbemittelkennzeichen als eigenes Feld ausgeben
Wenn der reine Code zusätzlich als eigenes Feld erscheinen soll, prüfen Sie zuerst, ob die Funktion aktiv ist. Andernfalls erscheint bei ausgeschalteter Funktion nichts.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsConfig.inserts.enabled }}
{{ foreach $item in $wsBasket.items }}
{{ if $item.insert }}
Werbemittelcode: {{= $item.insert }}
{{ /if }}
{{ /foreach }}
{{ /if }}
```
**Ergebnis**
Der Werbemittelcode erscheint nur bei aktiver Funktion und nur für Positionen, die einen Code tragen.
### Werbemittelkennzeichen in der Direktbestellung erfassen
Auf der Direktbestellseite (Template `modules/directOrder.htm`, Modul [\$wsDirectOrder](/frontend/referenz/module/wsdirectorder)) können Kunden die Artikelnummern zeilenweise eingeben. Ein eigenes Eingabefeld für das Werbemittelkennzeichen ist nicht erforderlich. Der Kunde gibt die Artikelnummer zusammen mit dem Code in das bestehende Artikelnummernfeld ein, so wie sie im Katalog abgedruckt ist. Der Shop trennt den Code anhand der [Konfiguration](#konfiguration) ab:
| **Konfiguration** | **Eingabe** | **Artikelnummer** | **Code** |
| - | - | - | - |
| Trennzeichen `/`, Position dahinter | `123456/AB` | `123456` | `AB` |
| Trennzeichen `/`, Position davor | `AB/123456` | `123456` | `AB` |
| Kein Trennzeichen, `insertCodeLength` `2`, Position davor | `AB123456` | `123456` | `AB` |
| Kein Trennzeichen, `insertCodeLength` `2`, Position dahinter | `123456AB` | `123456` | `AB` |
Dabei geht der Shop in dieser Reihenfolge vor:
1. Er prüft, ob die gesamte Eingabe eine gültige Artikelnummer ist. Dann trennt er nichts ab. So wird eine echte Artikelnummer, die das Trennzeichen zufällig enthält, nicht zerschnitten.
2. Andernfalls trennt er den Code ab und prüft die verbleibende Nummer. Steht der Code dahinter, trennt der Shop am letzten Trennzeichen. Steht er davor, trennt der Shop am ersten Trennzeichen. Aus der Nummer `123-456-09` mit dem Trennzeichen „`-`” wird somit die Nummer `123-456` mit dem Code `09`.
3. Der abgetrennte Code wird gegen die gültigen Codes des gefundenen Produkts geprüft, wie unter [Wie der Shop ein Werbemittelkennzeichen ermittelt](#wie-der-shop-ein-werbemittelkennzeichen-ermittelt) beschrieben.
Eingaben ohne Kennzeichen funktionieren unverändert, das heißt, es können weiterhin Artikelnummer, Produkt-ID, EAN oder ISBN verwendet werden.
Damit die Kunden wissen, dass sie den Code eingeben können, kann das Feld für die Artikelnummer einen entsprechenden Hinweis erhalten. Im folgenden Beispiel wird der Platzhalter nur bei aktiver Funktion ergänzt:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
```
**Ergebnis**
Bei aktiver Funktion lautet der Platzhalter „Artikelnummer mit Werbemittelkennzeichen“. Gibt der Kunde beispielsweise die Nummer `123456/AB` ein, so erfasst der Shop das Produkt mit der Nummer `123456` und dem Code `AB` im Bestellschein. Dieser steht anschließend in `$wsDirectOrder.items[…].insert`.
Die Position gelangt erst mit dem separaten Formular in den Warenkorb, das die erfassten Positionen über die Aktion `BasketItemAdd` übernimmt. Damit der Code dabei erhalten bleibt, schickt das Formular je Position zusätzlich das Feld `multiProducts..insert` mit. Ein vollständiges Beispiel finden Sie unter [Positionen in den Warenkorb übernehmen](/frontend/referenz/module/wsdirectorder#positionen-in-den-warenkorb-übernehmen).
### Bestellhistorie
Die Bestellhistorie arbeitet nicht mit dem Warenkorb, sondern mit den gespeicherten Bestelldaten (`$order.orderList.item`). Auch dort setzt das Template die Anzeige selbst zusammen. Dafür eignet sich ebenfalls die Komponente `components/itemNumberWithInsert.htm`, der Sie die Artikelnummer (`itemNumber`) und den gespeicherten Code (`insert`) der Bestellposition übergeben. Beachten Sie, dass `itemNumber` in den Bestelldaten die Nummer des Hauptprodukts ist, auch bei bestellten Varianten.
## Weiterführende Links
* [\$wsInserts](/frontend/referenz/module/wsinserts): je Produkt gemerktes Kennzeichen über `$wsInserts.byProduct` sowie die Einstellungen (aktiv, Trennzeichen, Position, Standardcode).
* [\$wsConfig](/frontend/referenz/module/wsconfig): Einstellungen über `$wsConfig.inserts` (aktiv, Trennzeichen, Position, Standardcode).
* [\$wsBasket](/frontend/referenz/module/wsbasket): Ausgabe je Position über `$item.insert` und `$item.itemNumber`.
* [\$wsViews](/frontend/referenz/module/wsviews): Erzeugung von View-URLs (`url()`, `viewUrl()`), an die sich der `insert`-Parameter anhängen lässt.
* [content - Katalog](/konfiguration/content-katalog-kategorien-produkte): Konfigurationsblock `content.inserts` und die zwingende Feldzuordnung `usedFields.products`.
* [API-Referenz Produkte](/schnittstellen/admin-interface-api/api-referenz-produkte): Pflege der zulässigen Codes je Produkt (`custom.validInsertCodes`). Setzt die Feldzuordnung `usedFields.products` voraus (siehe [Voraussetzungen](#voraussetzungen)).
* [API-Referenz Konfiguration](/schnittstellen/admin-interface-api/api-referenz-konfiguration): Pflege des Konfigurationsblocks `content.inserts` über die Konfigurationsknoten-Endpunkte.
* [Storefront-API Warenkorb](/schnittstellen/storefront-api/storefront-api-warenkorb): Setzen und Auslesen des Kennzeichens über das `insert`-Feld sowie `GET /api/v1/config/inserts`.
# Übersicht - Zahlungsarten
Source: https://dokumentation.websale.de/frontend/funktionsubersicht/zahlungsarten
Grundprinzip der Zahlungsarten-Konfiguration: Knoten unter payment.payment anlegen, Aktivierung, Bezeichnungen, Icons und Validierungen festlegen.
## Grundprinzip
Jede Zahlungsart wird zunächst als eigener Konfigurationsknoten unter `payment.payment.` angelegt.
Die ID ist frei wählbar; es gibt keine fest vorgegebenen Bezeichnungen pro Zahlungsart. Dadurch können Zahlungsarten beispielsweise unter Knoten wie `payment.payment.bill`, `payment.payment.applepay`, `payment.payment.googlepay` oder `payment.payment.paypal` definiert werden.
In `payment.payment` werden unter anderem festgelegt, ob die Zahlungsart aktiv ist, welche Bezeichnung sie im Checkout trägt, welches Bild oder Icon verwendet wird und welche Regeln und Einschränkungen für ihre Verfügbarkeit gelten. Die offizielle Doku beschreibt `payment.payment` genau als den Bereich, in dem Zahlarten zusammengefasst und Eigenschaften wie `active`, `id`, `name`, `image`, `validations` sowie die Anbindung an Online-Clearing konfiguriert werden.
Typische Angaben einer Zahlungsart sind zum Beispiel:
* Aktiv-/Inaktiv-Schaltung
* Name und Beschreibung
* Bild oder Icon
* Zulässigkeit oder Ausschluss für bestimmte Länder
* Zulässigkeit oder Ausschluss für bestimmte Produkte oder Warenkörbe
* Zusätzliche Eingabefelder, beispielsweise das Geburtsdatum für den Kauf auf Rechnung (siehe [Zusatzfelder für Zahlungsarten](/konfiguration/payment-zahlungsmethoden#paymentpaymentfield---zusatzfelder-für-zahlungsarten)), oder Prüfungen
* Art der Zahlungsabwicklung
Weitere Informationen zu den allgemeinen Konfigurationsmöglichkeiten einer Zahlungsart finden sich auf der Seite [payment - Zahlungsmethoden](/konfiguration/payment-zahlungsmethoden).
***
## Offline- und Online-Zahlungsarten
Für die Konfiguration ist zunächst wichtig, zwischen **offline** und **online** abgewickelten Zahlungsarten zu unterscheiden. Die Doku nennt für `type` ausdrücklich typische Werte wie `offline` für manuell abgewickelte Zahlungen und `online` für Zahlungen über einen Provider.
### Offline-Zahlungsarten
Bei einer reinen Offline-Zahlungsart ist die Konfiguration mit `payment.payment.` im Regelfall abgeschlossen. Die Zahlungsart wird angelegt, benannt und im Checkout angeboten, ohne dass eine zusätzliche Provider-Anbindung erforderlich ist.
Ein typisches Beispiel dafür ist **Vorauskasse**. Hier reicht die Definition der Zahlart in `payment.payment.prepayment`, da keine Echtzeit-Kommunikation mit einem Zahlungsdienstleister notwendig ist.
**Beispielkonfiguration** `payment.payment.prepayment`
```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
"active": true,
"basicCost": null,
"description": "Text",
"discount": 0,
"displayedPaymentTypes": [],
"freeFields": null,
"id": "prepayment",
"image": "",
"labels": null,
"name": "Vorauskasse",
"onlineClearing": null,
"orderText": "Text",
"provider": "",
"type": "",
"validations": [ ]
}
```
### Online-Zahlungsarten
Bei Online-Zahlungsarten wird die Zahlungsart ebenfalls zunächst unter `payment.payment.` angelegt. Die Zahlungsart selbst bleibt immer zunächst eine eigenständige Konfiguration unter `payment.payment.ID`.
Erst wenn sie online abgewickelt werden soll, kommt eine passende Online-Anbindung hinzu. Dabei wird die Zahlungsart über den Parameter `onlineClearing` mit einem konkreten Provider verknüpft, beispielsweise `payment.paypal-checkout`.
**Beispielkonfiguration** `payment.payment.GooglePay`
```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
"active": false,
"basicCost": null,
"description": "Text",
"discount": 0,
"displayedPaymentTypes": [],
"freeFields": null,
"id": "paypalCheckoutGooglePay",
"image": "",
"labels": null,
"name": "GooglePay",
"onlineClearing": {
"options": {
"type": "googlePay",
"view": "paypal_checkout_pending.htm"
},
"service": "payment.paypal-checkout"
},
"orderText": "Text",
"provider": "",
"type": "",
"validations": [ ]
}
```
Das gleiche Vorgehen gilt für Google Pay und Apple Pay über Stripe. Läuft der Bestellablauf über mehrere Seiten, werden für die beiden Wallets eigene Zahlungsarten mit Stripe als Clearing-Service angelegt, damit das Template sie getrennt behandeln kann. Den Einbau beschreibt [Stripe im Frontend](/frontend/funktionsubersicht/zahlungsarten/stripe#mehrseitiger-bestellablauf-google-pay-und-apple-pay).
# stripe
Source: https://dokumentation.websale.de/frontend/funktionsubersicht/zahlungsarten/stripe
Zahlungsart Stripe im Checkout einrichten: relevante Konfigurationen, Module wie $wsStripe und $wsCheckout sowie Aktionen für den Bestellprozess.
## Konfigurationen
Folgende Einstellungen sind relevant für die Konfiguration der Zahlungsart stripe:
***
## Module
Folgende Module sind relevant für die Integration der Zahlungsart stripe im Bestellprozess:
* [\$wsStripe](/frontend/referenz/module/wsstripe) - stripe-Zahlungsarten Modul
* [\$wsCheckout](/frontend/referenz/module/wscheckout) - Checkout-Zustand, Adressen, Versand, Zahlung, Probleme, Summen
* [\$wsActions](/frontend/referenz/module/wsactions) - Aktionen erzeugen und auswerten
* [\$wsAccount](/frontend/referenz/module/wsAccount) - Login-Status, E-Mail, Adressen, loadAddress()
* [\$wsViews](/frontend/referenz/module/wsviews) - Aktuelle URL, Zielseiten, View-URLs
* [\$wsBasket](/frontend/referenz/module/wsbasket) - Warenkorb und Bestellübersicht
* [\$wsConfig](/frontend/referenz/module/wsconfig) - Konfigurationswerte, zum Beispiel Anreden und Währung
***
## Aktionen
Folgende Aktionen sind relevant für die Integration der Zahlungsart stripe:
***
## Zusätzliche relevante Informationen
Folgende zusätzlichen Inhalte müssen für die Zahlungsart integriert werden.
### Frontend-Integration
Stripe stellt ein eigenes JavaScript-SDK bereit, das in das Template eingebunden werden muss. Es übernimmt die Darstellung der Zahlungsfelder und die Kommunikation mit Stripe.
**HTML-Struktur**
Folgender HTML-Block muss im Template plaziert werden:
* `#wsStripePaymentElement` ist der Container, in den Stripe die Zahlungsfelder (beispielsweise Kreditkartennummer oder PayPal-Button) automatisch einbettet
* Das Formular sendet beim Klick auf “Mit Stripe bezahlen” den Bezahlvorgang ab
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
```
**JavaScript**
Der folgende Script-Block muss direkt nach dem HTML-Block eingefügt werden. Er muss in `{{ autoescape “js” }}` eingeschlossen sein, damit Template-Variablen im JavaScript-Kontext korrekt verarbeitet werden.
Der Ablauf im Script ist folgender:
1. **Stripe initialisieren** - Das SDK wird mit den Zugangsdaten aus [\$wsStripe.configuration](/frontend/referenz/module/wsstripe) gestartet
2. **Zahlungsfelder anzeigen** - Stripe rendert die Zahlungsauswahl (Kreditkarte, PayPal und weitere) in den `#wsStripePaymentElement`-Container. Die Adresseingabefelder von Stripe werden dabei deaktiviert, weil die Adresse des Kunden bereits im Shop bekannt ist und automatisch übergeben wird.
3. **Bezahlung auslösen** - Beim Absenden des Formulars werden die eingegebenen Zahlungsdaten zusammen mit der Rechnungsadresse aus [\$wsAccount](/frontend/referenz/module/wsAccount) an Stripe geschickt. Stripe gibt dafür ein Confirmation-Token zurück.
4. **Token an den Shop senden** - Das Token wird an den Shop übermittelt, der damit den eigentlichen Zahlungsvorgang bei Stripe startet.
5. **Ergebnis verarbeiten** - Schlägt die Zahlung fehl, wird eine Fehlermeldung angezeigt. Ist eine zusätzliche Bestätigung nötig, beispielsweise 3D Secure, übernimmt Stripe das automatisch.
6. **Weiterleitung** - Nach erfolgreicher Zahlung wird der Kunde zur Bestellbestätigungsseite weitergeleitet.
```javascript theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ autoescape "js" }}
{{ /autoescape }}
```
### Mehrseitiger Bestellablauf: Google Pay und Apple Pay
Bei der oben beschriebenen Frontend-Integration wird davon ausgegangen, dass das Payment-Element auf der letzten Seite des Bestellablaufs, also auf der Seite der Bestellübersicht, steht.
Bei einem Bestellablauf mit mehreren Schritten ist es sinnvoll, das Widget bereits auf der Seite mit den Zahlungsarten zu laden, damit der Kunde seine Zahlungsdaten direkt bei der Auswahl eingeben kann. Das funktioniert für Kreditkarte und die übrigen Stripe-Zahlungsarten. Google Pay und Apple Pay verhalten sich anders und benötigen eine eigene Integration. Der folgende Abschnitt erklärt zunächst, woran das liegt, und zeigt anschließend den Einbau.
#### Warum Wallets eine Sonderrolle haben
Für Stripe sind Google Pay und Apple Pay keine eigenen Zahlungsarten, sondern sie hängen an der Zahlungsart `card`. Sobald `card` erlaubt ist und das Gerät des Kunden ein Wallet unterstützt, blendet das Payment-Element das Wallet von sich aus ein. Daraus ergeben sich drei Punkte, die in einem mehrseitigen Bestellablauf zu Problemen führen können.
1. **Der Wallet-Dialog schließt die Zahlung ab.** Klickt der Kunde darin auf "Bezahlen", autorisiert er die Zahlung sofort. Steht das Widget auf der Seite mit den Zahlungsarten, hat der Kunde bereits bezahlt, bevor er die Bestellbestätigung gesehen, die Versandart gewählt und die AGB bestätigt hat.
2. **Der Betrag steht fest, sobald das Widget geladen ist.** `stripe.elements()` erhält beim Aufruf die Parameter `amount` und `currency` und genau dieser Betrag erscheint im Wallet-Dialog. Ändert sich die Summe danach noch, beispielsweise durch eine andere Versandart oder Kosten der Zahlungsart, zeigt der Dialog weiterhin den alten Betrag an. Das lässt sich nur mit `elements.update({ amount: ... })` korrigieren, und zwar bevor der Dialog geöffnet wird.
3. **Der Wallet-Dialog erfordert eine unmittelbare Nutzeraktion.** Browser öffnen den Apple-Pay- und Google-Pay-Dialog nur durch direkten Klick. Eine vorgeschaltete AJAX-Prüfung, wie sie auf einer Seite mit Zahlungsarten üblich ist, kostet diese Nutzeraktion und der Dialog öffnet sich nicht mehr.
Die Adresse aus dem Wallet hat bei Google Pay und Apple Pay Vorrang vor den `billing_details`, die das Template mitgibt. Deshalb kann bei Stripe eine andere Rechnungsadresse stehen als im Shop. Die Bestellung wird vom Shop weiterhin mit den im Checkout gewählten Adressen angelegt.
#### Empfohlener Einbau: Widget auf der Bestellübersicht
Am einfachsten ist es, das Payment-Element dort zu belassen, wo die Integration es vorsieht: auf der Bestellübersicht, also Schritt 3 im [MultiPage Checkout](/frontend/praxisbeispiele/bestellablauf-bestellfunktionen/multipage-checkout). Auf der Zahlungsarten-Seite wählt der Kunde nur aus, das Widget wird dort nicht geladen. Damit fallen alle drei Punkte oben weg, weil Betrag, Versandart und AGB-Bestätigung zu diesem Zeitpunkt feststehen.
Wenn das Widget trotzdem früher angezeigt werden soll, damit der Kunde seine Zahlungsdaten bereits bei der Auswahl eingeben kann, muss die Zahlungsart schon vor dem Laden des Widgets feststehen. Dafür gibt es zwei Varianten. Beide beruhen darauf, dass im Shop eigene Zahlungsarten mit Stripe als Clearing-Service angelegt werden und das Template das Widget an die gewählte Zahlungsart klammert. Sie unterscheiden sich darin, wie weit diese Aufteilung geht.
#### Variante 1: eigene Zahlungsarten für Google Pay und Apple Pay
Bei dieser Variante werden lediglich die beiden Wallets voneinander getrennt. Alle übrigen Zahlungsarten von Stripe bleiben wie bisher in einer Zahlungsart zusammen.
##### Konfiguration
Legen Sie im Konfigurationsdienst unter [`payment.payment`](/konfiguration/payment-zahlungsmethoden#paymentpayment---zahlungsarten-anlegen) je eine eigene Zahlungsart für Google Pay und Apple Pay an und hinterlegen Sie bei beiden Stripe als Clearing-Service unter `onlineClearing`. Neben der bestehenden Stripe-Zahlungsart stehen dann drei Einträge zur Auswahl, beispielsweise mit den Kennungen `stripe`, `googlePay` und `applePay`.
Damit weiß der Shop ab der Zahlungsarten-Seite, welches Wallet der Kunde gewählt hat. Das Template kann sich im weiteren Verlauf darauf beziehen.
##### Zahlungsarten-Seite
Auf der Seite "Zahlungsarten" laden Sie das Payment-Element wie gewohnt, schalten die Wallets dort aber ab. Der Kunde gibt dort also nur seine Karten- oder anderen Zahlungsdaten ein. Es kann sich kein Wallet-Dialog öffnen.
```javascript theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
const paymentElement = elements.create('payment', {
// Google Pay und Apple Pay auf dieser Seite nicht anbieten
wallets: {
applePay: 'never',
googlePay: 'never'
},
fields: {
billingDetails: {
// wie in der Integration oben
}
}
});
paymentElement.mount("#wsStripePaymentElement");
```
Wurde Google Pay oder Apple Pay als Zahlungsart gewählt, wird auf dieser Seite gar kein Widget geladen. Binden Sie die Ausgabe stattdessen an die gewählte Zahlungsart:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsCheckout.selectedPayment == "stripe" }}
{{# Payment Element ohne Wallets, siehe oben #}}
{{ /if }}
```
##### Bestellübersicht
In der Bestellübersicht wird für Google Pay und Apple Pay statt des Payment Elements das Express Checkout Element angezeigt. Es wird der Wallet-Button angezeigt und die Zahlung wird erst ausgelöst, wenn alle Angaben feststehen.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsCheckout.selectedPayment == "googlePay" or $wsCheckout.selectedPayment == "applePay" }}
{{ else }}
{{ /if }}
```
Das Express-Checkout-Element hängt an derselben `elements`-Instanz wie das Payment Element. Über `allowedPaymentMethodTypes: ['card']` bleiben nur die beiden Wallets übrig. Über `paymentMethods` wird das nicht gewählte Wallet ausgeblendet.
```javascript theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
const options = {
mode: 'payment',
amount: {{= $wsCheckout.getAmountInSmallestUnit($wsCheckout.sum.total) }},
currency: '{{= lower($wsCheckout.sum.currency) }}',
paymentMethodCreation: 'manual',
// Apple Pay und Google Pay hängen an der Zahlungsart "card"
allowedPaymentMethodTypes: ['card'],
appearance,
};
const elements = stripe.elements(options);
const expressCheckoutElement = elements.create('expressCheckout', {
// nur das Wallet anzeigen, das der Kunde gewählt hat
paymentMethods: {
applePay: '{{ if $wsCheckout.selectedPayment == "applePay" }}auto{{ else }}never{{ /if }}',
googlePay: '{{ if $wsCheckout.selectedPayment == "googlePay" }}auto{{ else }}never{{ /if }}'
},
// Wallets geben die E-Mail-Adresse sonst nicht heraus
emailRequired: true
});
// Unterstützt das Gerät kein Wallet, bleibt sonst eine leere Fläche stehen
expressCheckoutElement.on('availablepaymentmethodschange', ({ paymentMethods }) => {
if (!paymentMethods) {
document.querySelector("#wsStripeExpressCheckoutHint").style.display = "block";
}
});
expressCheckoutElement.on('confirm', async (event) => {
const {error: submitError} = await elements.submit();
if (submitError) {
showMessage(submitError.message);
return;
}
const {error, confirmationToken} = await stripe.createConfirmationToken({
elements,
params: {
// Rechnungsadresse wie in der Integration oben mitgeben
}
});
if (error) {
showMessage(error.message);
return;
}
// Ab hier identisch zur Integration oben: Confirmation Token an den Shop
// schicken, Antwort auswerten und auf die Bestellbestätigung weiterleiten
});
expressCheckoutElement.mount("#wsStripeExpressCheckoutElement");
```
#### Variante 2: jede Stripe-Zahlungsart einzeln anlegen
Diese Variante geht einen Schritt weiter. Anstatt nur die Wallets abzutrennen, legen Sie jede Stripe-Zahlungsart einmal im Shop an, beispielsweise Kreditkarte, SEPA-Lastschrift, Klarna und PayPal, jeweils mit Stripe als Clearing-Service. Der Kunde wählt damit bereits auf der Zahlungsarten-Seite die konkrete Zahlungsart aus, und das Widget lädt nur noch diese eine.
Gesteuert wird das über `allowedPaymentMethodTypes`. Die Option nimmt die Stripe-Kennungen der Zahlungsarten entgegen, beispielsweise `card`, `sepa_debit`, `klarna` oder `paypal`. Das Template setzt die passende Kennung zur gewählten Zahlungsart:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsCheckout.selectedPayment == "stripeCard" }}{{ var $stripeType = "card" }}{{ /if }}
{{ if $wsCheckout.selectedPayment == "stripeSepa" }}{{ var $stripeType = "sepa_debit" }}{{ /if }}
{{ if $wsCheckout.selectedPayment == "stripeKlarna" }}{{ var $stripeType = "klarna" }}{{ /if }}
```
```javascript theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
const options = {
mode: 'payment',
amount: {{= $wsCheckout.getAmountInSmallestUnit($wsCheckout.sum.total) }},
currency: '{{= lower($wsCheckout.sum.currency) }}',
paymentMethodCreation: 'manual',
// nur die Zahlungsart laden, die der Kunde gewählt hat
allowedPaymentMethodTypes: ['{{= $stripeType }}'],
appearance,
};
const elements = stripe.elements(options);
```
Für Google Pay und Apple Pay gilt dasselbe wie in Variante 1: Beide hängen an `card` und erhalten `allowedPaymentMethodTypes: ['card']` und werden über `wallets` bzw. `paymentMethods` ein- und ausgeblendet. Der Einbau auf Zahlungsarten-Seite und Bestellübersicht ist identisch zu Variante 1.
#### Welche Variante wann sinnvoll ist
Variante 1 ist der kleinere Eingriff. Sie lohnt sich, wenn der Shop das Stripe-Widget weiterhin als Zahlungsart führt und nur das Problem mit den Wallets lösen möchte.
Variante 2 lohnt sich, wenn der Kunde bereits in der Zahlungsartenauswahl des Shops die konkrete Zahlungsart sehen soll, statt sie erst im Stripe-Widget auszuwählen. Der Konfigurationsaufwand ist jedoch höher, weil jede Zahlungsart einzeln angelegt und gepflegt werden muss.
#### Vor dem Livegang prüfen
* **Domain registrieren.** Google Pay und Apple Pay erscheinen nur auf Domains, die bei Stripe als Payment Method Domain registriert sind, und zwar getrennt für Testmodus und Livemodus.
* **HTTPS.** Das Express Checkout Element arbeitet mit einem iframe und setzt eine Auslieferung über `https://` voraus.
* **Betrag im Wallet-Dialog.** Vergleichen Sie den Betrag im Apple-Pay- beziehungsweise Google-Pay-Dialog mit der Bestellsumme, insbesondere wenn Versandart oder Kosten der Zahlungsart die Summe verändern.
* **Geräte ohne Wallet.** Testen Sie den Fall, dass das Wallet nicht verfügbar ist, und stellen Sie sicher, dass der Kunde dann eine andere Zahlungsart wählen kann.
* **Rechnungsadresse.** Prüfen Sie im Stripe-Dashboard, welche Adresse bei der Zahlung ankommt, wenn das Wallet eine eigene Adresse liefert.
***
## Weiterführende Links
* Generelle Doku für das Stripe Frontend: [https://docs.stripe.com/js](https://docs.stripe.com/js)
* Express Checkout Element (Google Pay und Apple Pay): [https://docs.stripe.com/elements/express-checkout-element](https://docs.stripe.com/elements/express-checkout-element)
* Domain für Wallets registrieren: [https://docs.stripe.com/payments/payment-methods/pmd-registration](https://docs.stripe.com/payments/payment-methods/pmd-registration)
* [MultiPage Checkout](/frontend/praxisbeispiele/bestellablauf-bestellfunktionen/multipage-checkout)
# Getting Started
Source: https://dokumentation.websale.de/frontend/getting-started
Schritt-für-Schritt-Einstieg in einen WEBSALE-Onlineshop: Design anpassen, Produkte und Kategorien anlegen, Zahlungsarten konfigurieren und Shop SEO optimieren.
Ein WEBSALE-Onlineshop bietet zahlreiche Möglichkeiten zur individuellen Anpassung und Konfiguration. Damit Sie schnell und effizient starten können, führt diese Anleitung Sie Schritt für Schritt durch die wichtigsten ersten Aufgaben.
Von der grundlegenden Shop-Konfiguration über die visuelle Anpassung der Storefront bis hin zur Einrichtung von Produkten, Kategorien und Zahlungsarten – diese Anleitung zeigt Ihnen, wie Sie Ihren Shop optimal einrichten.
Jeder Schritt enthält praktische Anleitungen und Erklärungen, damit Sie direkt loslegen können:
### Arbeiten mit GitLab
* [Kennenlernen der WEBSALE GitLab Pipeline](/frontend/getting-started/arbeiten-mit-gitlab)
### Design & Branding anpassen
* Logo austauschen
* Farben und Schriftarten definieren
* Startseite und Layout anpassen
### Produkte & Kategorien verwalten
* Kategorien strukturieren und organisieren
* Produkte anlegen und bearbeiten
* Produktbilder und Beschreibungen hinzufügen
### Grundlegende Shop-Konfiguration
* Währungen, Steuersätze etc. einrichten
* Zahlungsarten konfigurieren
* Versandoptionen festlegen
### SEO & Performance optimieren
* Meta-Titel, Beschreibungen und URLs anpassen
* Bildoptimierung
### Rechtliche Anforderungen berücksichtigen
* DSGVO-Konformität sicherstellen
* Impressum und Datenschutzrichtlinien ergänzen
* Cookie-Banner einrichten
### Tests & Veröffentlichung
* Testbestellungen durchführen
* Checkout-Prozess überprüfen
* Letzte Anpassungen vor dem Livegang vornehmen
### 🚧 **Hinweis: Inhalte in Bearbeitung** 🚧
Diese Seite wird derzeit aktualisiert und um detaillierte Anleitungen zu den einzelnen Schritten erweitert. Die Übersicht bietet bereits einen strukturierten Leitfaden für den Start mit Ihrem WEBSALE-Onlineshop, jedoch sind einige Abschnitte noch in der Bearbeitung. Die fehlenden Inhalte werden **nach und nach ergänzt**, um Ihnen eine umfassende Schritt-für-Schritt-Anleitung zur Verfügung zu stellen. Schauen Sie regelmäßig vorbei, um die neuesten Updates zu erhalten.
Vielen Dank für Ihr Verständnis! 😊
# Arbeiten mit GitLab
Source: https://dokumentation.websale.de/frontend/getting-started/arbeiten-mit-gitlab
Mit dem GitLab-Repository des Shops arbeiten: Zugriff auf gitlab.websale.cloud sowie Versionierung der Layout- und Template-Dateien einrichten.
Zu jedem Shop wird im Standard ein eigenes GitLab-Repository mitgeliefert. Dieses Repository dient zur Verwaltung und Versionierung der Layout- und Template-Dateien, die für das Erscheinungsbild des Shops verantwortlich sind.
***
## Zugriff
Das WEBSALE GitLab ist unter folgender URL erreichbar: [https://gitlab.websale.cloud](https://gitlab.websale.cloud)
Die Zugangsdaten werden beim Bereitstellen des Shops durch die WEBSALE AG übermittelt.\
Für zusätzliche Benutzer kann über das Beauftragungsportal der WEBSALE AG ein weiterer Zugriff beantragt werden.
***
## Einstellungen (Settings → CI/CD → Variables)
Im Menü des Projekts unter Settings → CI/CD → Variables sind Umgebungsvariablen für die Shop-Pipeline definiert.
### Editierbare Variablen
| **Variable** | **Beschreibung** |
| - | - |
| `AUTO_COMPILE_TEMPLATES` | Steuert, ob Templates nach Veröffentlichung im Main-Branch automatisch kompiliert werden.
- `true`: automatische Kompilierung beim Merge in *main*
- `false`: manuelle Kompilierung über das Admin Interface (Templates & Inhalte → Templates kompilieren). |
| `TEMPLATE_COMPILE_URL` | URL des Shops, über die die Kompilierung ausgeführt wird.
Diese URL muss bei Domainänderungen (z. B. Livegang von `shop-test.websale.net` auf `ihr-shop.de`) angepasst werden, da der Kompilierungsdienst nur über die aktive Shopdomain erreichbar ist. |
Angaben zu *Type*, *Environment*, *Visibility Flags* und *Key* dürfen für diese Variablen nicht verändert werden. Änderungen an diesen Einstellungen können zu Störungen oder Fehlern der Pipeline führen.
### Readonly Variablen
Diese Variablen können aktuell nur durch Mitarbeiter der WEBSALE AG bearbeitet werden.
| **Variable** | **Beschreibung** |
| - | - |
| `TEMPLATE_COMPILE_PASSWORD` | Passwort des Admin Interface Benutzers, der in `TEMPLATE_COMPILE_USER` hinterlegt ist. |
| `TEMPLATE_COMPILE_USER` | Benutzername des Admin Interface Benutzers.
Der `Template_Compile_User` ist ein separater technischer Benutzer im Admin Interface, der ausschließlich für die GitLab Pipeline vorgesehen ist.
Persönliche Admin-Logins werden dadurch nicht in GitLab hinterlegt und bleiben geschützt. |
| `S3_TEMPLATES_BUCKET` | `template`-Bucket im S3. |
| `S3_MEDIA_BUCKET` | `media`-Bucket im S3. |
| `S3_ENDPOINT` | URL des S3-Storages. |
| `AWS_DEFAULT_REGION` | Vorgegebene S3-Region von WEBSALE. |
| `AWS_SECRET_ACCESS_KEY` | Zugangsdaten für den Zugriff auf den S3-Speicher. |
| `AWS_ACCESS_KEY_ID` | Zugangsdaten für den Zugriff auf den S3-Speicher. |
***
## Verzeichnis- & Dateistruktur (Root-Ebene)
Das Repository enthält auf Root-Ebene folgende Einträge im Standard:
* `media/` (Verzeichnis)
* `templates/` (Verzeichnis)
* `.gitlab-ci.yml` (Datei)
* `README.md` (Datei)
### media
Das Verzeichnis `media` enthält alle statischen Ressourcen, die für das Design und Layout des Shops verwendet werden. Es ist im Standard wie folgt aufgebaut:
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
media
└── themes
└── default
├── favicon
├── fonts
│ └── bootstrap
├── images
├── pdf
├── scripts
└── scss
```
| **Verzeichnis** | **Beschreibung** |
| - | - |
| `favicon` | Icons und Favicons für den Browser |
| `fonts` | Schriftdateien (z. B. Bootstrap-Fonts) |
| `images` | Layoutgrafiken (z. B. Logos, Icons, Banner) |
| `pdf` | Statische PDF-Dateien (z. B. AGBs oder Datenschutzerklärung) |
| `scripts` | JavaScript-Dateien |
| `scss` | SCSS-Quelldateien für CSS Die kompilierten CSS-Dateien, die aus SCSS generiert werden, sind nicht Bestandteil des Repositories. Diese Dateien können bei Bedarf zu Debug-Zwecken über den Browser bzw. die Browserkonsole eingesehen werden. |
Unterhalb des Verzeichnisses `media/` können Ordner und Dateien nach Bedarf umbenannt, gelöscht oder neu angelegt werden. Diese Änderungen werden von der Pipeline beim Deployment berücksichtigt.
Beim Umbenennen oder Verschieben bestehender Ordner müssen ggf. auch die entsprechenden Pfadangaben in Templates, Stylesheets oder Skripten angepasst werden, damit Ressourcen weiterhin korrekt geladen werden.
### templates
Das Verzeichnis `templates` enthält die für das Shop-Frontend relevanten Template-Dateien. Es ist im Standard wie folgt aufgebaut:
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
templates
├── components
├── layouts
├── mails
└── views
```
| **Verzeichnis** | **Beschreibung** |
| - | - |
| `components` | Wiederverwendbare Template-Bausteine, HTML-Snippets und Widgets |
| `layouts` | Grundlayouts und Seitenstrukturen |
| `mails` | E-Mail-Vorlagen |
| `views` | Ansichten einzelner Shopseiten |
Unterhalb des Verzeichnisses `templates/` können Ordner und Dateien nach Bedarf umbenannt, gelöscht oder neu angelegt werden. Diese Änderungen werden von der Pipeline beim Deployment berücksichtigt.
Beim Umbenennen oder Verschieben bestehender Ordner müssen ggf. auch die verwendeten Pfade in den Templates angepasst werden, damit die entsprechenden Includes, Layouts und Views weiterhin gefunden werden.
### gitlab-ci.yml
Diese Datei definiert die CI/CD-Pipeline (Continuous Integration / Deployment) in Gitlab.
**Standardinhalt**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
### DO NOT EDIT THIS FILE! ###
### CHANGES CAN DESTROY THE SHOP! ###
include:
- remote: 'https://websale.de/git-design/ws_design/templates.yml'
```
Die hinter `remote:` angegebene Datei bindet die zentrale Pipeline-Vorlage der WEBSALE AG ein. Diese Remote-Datei kann ausschließlich durch die WEBSALE AG bearbeitet werden.
### Funktionsweise der WEBSALE Pipeline
Die Pipeline wird ausschließlich durch Commits im `main`-Branch gestartet und führt dabei folgende Jobs aus:
1. **Build (compile-sass)**
* Überwacht Änderungen in `media/themes/default/scss/**`
* Kompiliert SCSS-Dateien zu CSS (`media/themes/default/styles/`)
2. **Deploy (deploy-css)**
* Synchronisiert das CSS-Verzeichnis mit dem entsprechenden S3-Bucket
* Ausgenommen sind bestimmte Unterverzeichnisse (z. B. Fonts, Scripts, Favicons)
3. **Deploy (deploy-media-without-css)**
* Synchronisiert den übrigen `media`-Ordner (ohne Styles-Verzeichnis) mit dem S3-Bucket
4. **Deploy (deploy-templates)**
* Überträgt das Verzeichnis `templates` in den S3-Bucket
* Führt optional (abhängig von `AUTO_COMPILE_TEMPLATES`) die Template-Kompilierung über die API des Shops durch
Der Status der Pipeline sowie Log-Ausgaben der einzelnen Jobs können im GitLab unter **Build → Pipelines** eingesehen werden.
### README.md
Datei mit weiterführenden Informationen zum WEBSALE GitLab und dem WEBSALE Shopsystem.
***
## Eigene Versionsverwaltung verwenden
Verfügen Sie bereits über eine eigene Versionsverwaltung, die Sie für die Entwicklung des WEBSALE-Shops nutzen möchten (z. B. GitHub, eigenes GitLab, o. Ä.), ist dies grundsätzlich möglich.
**Funktionsprinzip**
* Die Entwicklung findet wie gewohnt in Ihrer bestehenden Versionsverwaltung statt.
* Über eine eigene Pipeline (oder manuell per Git-Remote) werden die relevanten Dateien in das zugehörige WEBSALE GitLab-Projekt übertragen und dort in den Branch `main` gepusht bzw. gemerged.
* Ab diesem Zeitpunkt greift die im WEBSALE GitLab-Projekt hinterlegte Pipeline und übernimmt wie gewohnt Build und Deployment (z. B. SCSS-Kompilierung, Medien- und Template-Deployment auf S3).
Für das Pushen in das WEBSALE GitLab-Projekt werden folgende Voraussetzungen benötigt:
* Ein GitLab-Benutzer für das betreffende WEBSALE Shop-Projekt mit Schreibrechten auf das Projekt bzw. den Branch `main`. Der notwendige Zugang wird durch die WEBSALE AG bereitgestellt.
Die Verwendung eines eigenen Repositories ersetzt nicht die Einrichtung des WEBSALE GitLab-Projekts. Die initiale Einrichtung des Projekts und der Benutzer kann derzeit nicht vollständig selbstständig vorgenommen werden und erfolgt vorerst über die WEBSALE AG.
***
## Hinweise & Einschränkungen
* Über das GitLab-Repository besteht kein Zugriff auf Produktdaten (z. B. Produkte, Preise, Bilder) oder Kundendaten. Produkt- und Kundendaten können über das Admin Interface, [REST APIs](/schnittstellen/admin-interface-api), Connectoren etc. verwaltet werden.
* Das Repository dient zur Verwaltung und zum Deployment von Shop-Templates und den dazugehörigen Mediendateien.
* Eigene Prozesse wie z. B. Docker-Container, zusätzliche Build-Jobs oder externe Programme sind mit der Standard-Pipeline nicht vorgesehen.
* Die Standard-Pipeline arbeitet aktuell ausschließlich im Branch `main`.
* Die Deployment-Jobs synchronisieren nur die Verzeichnisse `media` und `templates`. Oberhalb dieser Verzeichnisse angelegte Ordner werden nicht übertragen.
***
## Zugriff auf den Objektspeicher (S3)
Über GitLab besteht nur Zugriff auf die Shop-Templates bzw. das Theme/Template-Repository. GitLab ist damit der zentrale Ort für die Versionsverwaltung und die Bearbeitung des Template-Codes (z. B. Anpassungen am Frontend, Layouts, Komponenten, Styles).
Neben dem Zugriff über GitLab existiert zusätzlich ein Zugriff auf den Objektspeicher des Shops (S3). Über diesen Zugang erhält man Zugriff auf alle Dateien des Shops, z.B. Produktbilder, [JSON-Dateien](/schnittstellen/externe-datenschnittstelle-datei-bucket-basiert) etc.
# Praxisbeispiele - Gutscheine
Source: https://dokumentation.websale.de/frontend/praxisbeispiele/gutscheine
Praxisbeispiele für Gutscheine in WEBSALE: Eingabeformular mit maximumCount-Check, Validierung, Einlösen im Checkout sowie Download-Links für gekaufte Gutscheine.
In diesem Abschnitt finden Sie Praxisbeispiele für die Verwendung von Gutscheinen im Template. Die ersten Beispiele behandeln das Einlösen im Checkout, das letzte die Ausgabe gekaufter Gutscheine.
Gutscheine werden im Admin-Interface angelegt. Dies wird auf den Seiten [Gutscheine](/admin-interface/marketing/gutscheine) und [Kaufgutschein-Produkt anlegen](/admin-interface/katalog/produkte/kaufgutschein-produkt) beschrieben.
***
## Gutscheineingabe-Formular mit `maximumCount`-Check
Die Eingabe-Form wird nur angezeigt, solange weniger Gutscheine eingelöst sind als erlaubt. Sobald die Höchstgrenze erreicht ist, verschwindet das Formular automatisch.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionVoucherAdd = $wsActions.create("VoucherAdd") }}
{{ include "components/errorAlert.htm" with $cAction = $cActionVoucherAdd, $cViewEachField = true }}
{{ if len($wsVoucher.vouchers) < $wsVoucher.maximumCount }}
{{ /if }}
```
Fehlermeldungen (z.B. "Mindestbestellwert nicht erreicht") werden über `components/errorAlert.htm` definiert und ausgegeben.
***
## Liste eingelöster Gutscheine anzeigen
Pro Gutschein wird ein eigenes kleines Formular mit eindeutiger ID ausgegeben. Gültige Gutscheine erscheinen grün, ungültige rot.
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsVoucher.vouchers }}
Eingelöste Gutscheine
{{ foreach $cVoucher in $wsVoucher.vouchers }}
{{ var $cVoucherIsValid = $cVoucher.valid | ifNull(true) }}
{{ var $cActionVoucherDelete = $wsActions.create("VoucherDelete") }}
{{ /foreach }}
{{ /if }}
```
***
## Alle eingelösten Gutscheine im Warenkorb ausgeben
In diesem Beispiel werden alle eingelösten Gutscheine im Warenkorb ausgegeben. So sieht der Kunde transparent, welche Codes im System sind und welcher davon gerade greift. Nicht wirksame Gutscheine werden nicht in die Liste aufgenommen und werden über eine Fehlermeldung gekennzeichnet.
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cVoucherCount = 0 }}
{{ if $wsVoucher.vouchers }}
{{ foreach $cVoucher in $wsVoucher.vouchers }}
{{ $cVoucherCount = $cVoucherCount + 1 }}
{{ if $cVoucherCount == 1 }}Gutschein{{ else }}Weiterer Gutschein{{ /if }}
{{= $cVoucher.id }}
-{{= $cVoucher.value | currency }}
{{ /foreach }}
{{ /if }}
```
***
## Gutscheinfehler mit Grund und Gutschein-ID ausgeben
Statt eines allgemeinen Hinweises erhält der Kunde hier je Gutschein den konkreten Grund, warum der Gutschein nicht greift. Die Texte stammen aus [`checkout.voucherErrors`](/konfiguration/checkout-bestellablauf#checkout-vouchererrors-fehlertexte-zu-wirkungslosen-gutscheinen), der Fallback auf `code` greift nur, falls kein Text gepflegt ist.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsCheckout.isOrderBlockedByIneffectiveVoucher }}
Gutscheine können nicht eingelöst werden:
{{ foreach $cError in $wsCheckout.ineffectiveVoucherErrors }}
{{ if $cError.details.voucherId }}
-
Gutschein {{= $cError.details.voucherId }}:
{{= $cError.text | ifNull($cError.code) }}
{{ else }}
{{#
Steht die Berechnung des Mindestbestellwerts auf "sum", wird die Summe
aller Mindestbestellwerte geprüft. Dieser Fehler gehört zu keinem
einzelnen Gutschein und kommt daher ohne Gutschein-ID.
#}}
- {{= $cError.text | ifNull($cError.code) }}
{{ /if }}
{{ /foreach }}
{{ /if }}
```
Prüfen Sie `details.voucherId` immer vor der Ausgabe. Die Gutschein-ID fehlt bewusst, wenn der Fehler aus der Summenprüfung der Mindestbestellwerte stammt. Welcher Fehler wann entsteht, steht unter [Wann welcher Fehler entsteht](/konfiguration/checkout-bestellablauf#wann-welcher-fehler-entsteht).
***
## Kostenfreie Versandart für Gutschein-Warenkörbe
Enthält ein Warenkorb ausschließlich (Sofort-)Gutscheine, wird kein physischer Versand benötigt. Dafür lässt sich unter [`checkout.shippingMethod`](/konfiguration/checkout-bestellablauf#checkout-shippingmethod-versandarten) eine eigene, immer kostenfreie Versandart anlegen: Die Preisstaffel `basicCost` setzt die Kosten ab einer Zwischensumme von `0` auf `0`, und die Validierung [`shippingMethodValidation.productType`](/konfiguration/validierungs-und-prufservices) mit `rule: deny` sperrt die Versandart, sobald ein reguläres Produkt (Produkttyp `standard`) im Warenkorb liegt - sie ist also nur für reine Gutschein-Warenkörbe wählbar.
```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
"active": true,
"basicCost": [
{
"cost": 0,
"subtotal": 0
}
],
"description": "checkout.shippingMethod.INSTANT_VOUCHER.description",
"group": null,
"id": "INSTANT_VOUCHER",
"image": "",
"link": "",
"name": "checkout.shippingMethod.INSTANT_VOUCHER.name",
"orderText": "checkout.shippingMethod.INSTANT_VOUCHER.orderText",
"taxable": true,
"type": "standard",
"validations": [
{
"options": {
"rule": "deny",
"ruleList": [
"standard"
]
},
"service": "shippingMethodValidation.productType"
}
],
"weightCost": null
}
```
Der Wert `standard` in der `ruleList` ist der **Wert des Produkttyp-Feldes** der Produkte (das über `content.usedFields` als Produkttyp definierte Produktdatenfeld) - nicht zu verwechseln mit dem Parameter `type: "standard"` der Versandart selbst. Produkte, bei denen das Produkttyp-Feld nicht gesetzt ist, bestehen die Prüfung immer.
`name`, `description` und `orderText` verweisen im Beispiel auf Textbausteine, sodass die Texte je Sprache über den Textbaustein-Dienst gepflegt werden können.
***
## Gekaufte Gutscheine zum Download anbieten
Dieses Beispiel gehört nicht zum Einlösen, sondern zum Verkauf: Wurde ein [Kaufgutschein-Produkt](/admin-interface/katalog/produkte/kaufgutschein-produkt) bestellt, erzeugt der Shop beim Bestellabschluss je bestellter Einheit einen Gutscheincode. Die Codes einer Warenkorbposition stehen im Template unter `voucherIds` bereit, das zugehörige PDF wird über den URL-Parameter `wsfilter=pdf` aus dem am Produkt hinterlegten View-Template erzeugt.
Der folgende Block gibt je Position und Code einen Download-Link aus. Er eignet sich für die Bestellbestätigungsseite und für das E-Mail-Template der Bestellbestätigung.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $basketItem in $wsBasket.items }}
{{ if $basketItem.product.custom.voucherProductActive }}
{{ foreach $voucherId in $basketItem.voucherIds }}
Gutschein {{= $voucherId }} herunterladen
{{ /foreach }}
{{ /if }}
{{ /foreach }}
```
Der Typ `absolute` erzeugt eine vollständige URL, weil E-Mails keine relativen Links verarbeiten. Die Parameter `voucherId` und `productId` machen den Aufruf unabhängig von der Session, sodass der Link auch später noch funktioniert.
`voucher/default_voucher.htm` steht hier stellvertretend für das View-Template, das am Produkt im Feld "HTML-Template" hinterlegt ist. Wie PDF-Ansichten aufgebaut werden, beschreibt [PDF-Ansichten](/frontend/funktionsubersicht/pdf-ansichten).
Für die Weiterverarbeitung außerhalb des Shops stehen dieselben Angaben in den Bestelldaten unter `data.orderList.item[].voucher`, siehe [API-Referenz Bestellungen](/schnittstellen/admin-interface-api/api-referenz-bestellungen).
# Praxisbeispiele - Online-Bestellschein
Source: https://dokumentation.websale.de/frontend/praxisbeispiele/online-bestellschein
Online-Bestellschein für die Direktbestellung umsetzen: Produkte per Produktnummer erfassen, in den Warenkorb übernehmen und Eingaben über die Session halten.
Bei der Direktbestellung gibt der Käufer die Produktnummern der gewünschten Produkte in einen Bestellschein ein. Anschließend kann er alle erfassten Positionen mit einem Klick in den Warenkorb übernehmen. Voraussetzung hierfür ist, dass dem Kunden die entsprechenden Produktnummern vorliegen, beispielsweise anhand eines Katalogs.
Dafür ist nichts weiter erforderlich. Zusätzliche Skripte sind nicht nötig.
## Eingaben der Direktbestellung während einer Session halten
Der Shop speichert die bei einer Direktbestellung geprüften Produkte, die noch nicht in den Warenkorb gelegt wurden, in der Session. Im Cookie steht nur der Verweis auf die Session. Wenn `saveCountInSession` unter `checkout.directOrder` aktiviert ist, merkt sich der Shop dort auch die aktuelle Zahl der Eingabezeilen.
Wenn das Formular zur Direktbestellung später erneut aufgerufen wird, werden die gespeicherten Produktdaten automatisch in die entsprechenden Eingabefelder übernommen. So entfällt die erneute Eingabe von Produktnummer und Menge, wenn der Shopbesucher seine Auswahl noch nicht in den Warenkorb gelegt hat, sondern zunächst andere Seiten des Shops besucht hat.
## Aktionen
Folgende Aktionen stehen zur Verfügung:
### DirectOrderAdd
Diese Aktion prüft die Eingabe einer Zeile und trägt das Produkt in die Bestellschein-Liste ein. In den Warenkorb legt sie nichts, dafür gibt es einen eigenen Schritt, siehe [Positionen in den Warenkorb übernehmen](#positionen-in-den-warenkorb-übernehmen).
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $cProduct in range(0, $wsDirectOrder.currentLines - 1) }}
{{ var $cActionDirectOrderAdd = $wsActions.create("DirectOrderAdd", tag=string($cProduct)) }}
{{ /foreach }}
```
### DirectOrderDelete
Diese Aktion entfernt eine Zeile aus der Bestellschein-Liste. Der Warenkorb bleibt davon unberührt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $cProduct in range(0, $wsDirectOrder.currentLines - 1) }}
{{ var $cActionDirectOrderDelete = $wsActions.create("DirectOrderDelete", tag=string($cProduct)) }}
{{ /foreach }}
```
## Integration der Direktbestellung
### Template erstellen
Erstellen Sie im Verzeichnis `views/modules` eine neue Datei `directOrder.htm`.
In dieser Datei werden mehrere Reihen für die jeweiligen Bestellpositionen erzeugt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ extends "layouts/layout.htm" }}
{{ block content_main }}
Direktbestellung
{{ foreach $cProduct in range(0, $wsDirectOrder.currentLines - 1) }}
{{ var $cActionDirectOrderAdd = $wsActions.create("DirectOrderAdd", tag=string($cProduct)) }}
{{ var $cActionDirectOrderDelete = $wsActions.create("DirectOrderDelete", tag=string($cProduct)) }}
{{ /foreach }}
{{ /block }}
```
### Fehlermeldungen
Die Fehlermeldungen können entweder vor oder innerhalb des Form-Elements platziert werden. Die Aktion `DirectOrderAdd` meldet nicht alle Fehler am selben Feld:
* Fehler zur Menge stehen unter `errorsByField.quantity`.
* Fehler zur Artikelnummer und zum Produkt stehen unter `errorsByField.id`.
* Fehler der Artikelnummern-Felder aus `itemNumberFields` stehen unter dem Namen des jeweiligen Eingabefeldes. Das betrifft `itemNumberCheckFailed` und `missingId` bei einem leeren Pflichtfeld.
In diesem Beispiel werden Fehlermeldungen angezeigt, wenn die Menge eines Artikels falsch eingegeben wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $cProduct in range(0, $wsDirectOrder.currentLines - 1) }}
{{ var $cActionDirectOrderAdd = $wsActions.create("DirectOrderAdd", tag=string($cProduct)) }}
...
{{ if $cActionDirectOrderAdd.errorsByField.quantity }}
Es sind Fehler aufgetreten:
{{ foreach $err in $cActionDirectOrderAdd.errorsByField.quantity }}
- {{ if $err.text }}{{= $err.text }}{{ else }}{{= $err.code }}{{ /if }}
{{ /foreach }}
{{ /if }}
{{ /foreach }}
```
In diesem Beispiel werden Fehlermeldungen beim Hinzufügen eines Artikels angezeigt. Die zweite Schleife gibt zusätzlich die Fehler der Artikelnummern-Felder aus. Die Typprüfung ist nötig, weil `itemNumberFields` auch Trennzeichen enthält und diese keinen `name` haben.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $cProduct in range(0, $wsDirectOrder.currentLines - 1) }}
{{ var $cActionDirectOrderAdd = $wsActions.create("DirectOrderAdd", tag=string($cProduct)) }}
...
{{ if $cActionDirectOrderAdd.errorsByField.id }}
Es sind Fehler aufgetreten:
{{ foreach $err in $cActionDirectOrderAdd.errorsByField.id }}
- {{ if $err.text }}{{= $err.text }}{{ else }}{{= $err.code }}{{ /if }}
{{ /foreach }}
{{ /if }}
{{ foreach $field in $wsConfig.directOrder.itemNumberFields }}
{{ if $field.type == "field" and $cActionDirectOrderAdd.errorsByField[$field.name] }}
{{ foreach $err in $cActionDirectOrderAdd.errorsByField[$field.name] }}
{{ if $err.text }}{{= $err.text }}{{ else }}{{= $err.code }}{{ /if }}
{{ /foreach }}
{{ /if }}
{{ /foreach }}
{{ /foreach }}
```
Die Ausgabe je Artikelnummern-Feld ergänzt die Ausgabe von `errorsByField.id`, sie ersetzt diese nicht. Wenn sich die zusammengesetzte Artikelnummer keinem Produkt zuordnen lässt, meldet die Aktion `invalidId` am Feld `id`. Das gilt auch dann, wenn die Zeile gar kein Eingabefeld `id` enthält.
### Positionen in den Warenkorb übernehmen
Ein eigenes Formular legt die erfassten Positionen mit der Aktion `BasketItemAdd` in den Warenkorb. Dabei wird pro Position ein verstecktes Feld mit dem Namen `multiProducts..quantity` übermittelt. Bei aktiver [Werbemittelkennzeichnung](/frontend/funktionsubersicht/werbemittelkennzeichnung) wird zusätzlich das Feld `multiProducts..insert` übermittelt. Ohne diesen Schritt entsteht nie eine Bestellung.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionBasketItemAdd = $wsActions.create("BasketItemAdd", tag="directorder") }}
```
Mehr dazu steht in der Modulreferenz unter [Positionen in den Warenkorb übernehmen](/frontend/referenz/module/wsdirectorder#positionen-in-den-warenkorb-übernehmen).
### Seite im Footer verlinken
Sie können in jedem Template den Link zur Direktbestellung integrieren. Dieser lautet:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Direktbestellung
```
# Praxisbeispiele - Testmodus
Source: https://dokumentation.websale.de/frontend/praxisbeispiele/praxisbeispiele-testmodus
Testmodus mit Passwortformular aktivieren: Eingabemaske bauen, Debug-Modus einschalten und Testmodus über $wsTestMode wieder deaktivieren.
# Formular zur Eingabe des Passwortes
* Eingabemaske für das Testmodus-Passwort
* Aktivieren des Debug-Modus
* Deaktivieren des Testmodus
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if not $wsTestMode.active }}
{{ var $cActionTestModeOn = $wsActions.create("TestModeOn") }}
{{ if $cActionTestModeOn.error }}
Es sind Fehler aufgetreten:
{{ foreach $error in $cActionTestModeOn.errors }}
{{ if $error.text }}
{{= $error.text }}
{{ else }}
{{= $error.code }}
{{ /if }}
{{ /foreach }}
{{ /if }}
{{ else}}
{{ var $cActionTestModeOff = $wsActions.create("TestModeOff") }}
{{ if $cActionTestModeOff.error }}
Es sind Fehler aufgetreten:
{{ foreach $error in $cActionTestModeOff.errors }}
{{ if $error.text }}
{{= $error.text }}
{{ else }}
{{= $error.code }}
{{ /if }}
{{ /foreach }}
{{ /if }}
{{ /if }}
```
# Test-Modus Ändern
Im aktiven Testmodus können das Debugging und die Simulation fehlgeschlagener Zahlungen ein- bzw. ausgeschaltet werden, ohne dass der Testmodus beendet werden muss.
Die Aktion `TestModeChange` setzt alle Schalter zurück. Ein Schalter, der im Formular fehlt oder nicht aktiviert ist, wird deaktiviert. Stellen Sie deshalb sicher, dass alle Schalter im Formular abgebildet sind.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if not $wsTestMode.active }}
...
{{ else}}
...
{{ var $cActionTestModeChange = $wsActions.create("TestModeChange") }}
{{ if $cActionTestModeChange.error }}
Es sind Fehler aufgetreten:
{{ foreach $error in $cActionTestModeChange.errors }}
{{ if $error.text }}
{{= $error.text }}
{{ else }}
{{= $error.code }}
{{ /if }}
{{ /foreach }}
{{ /if }}
{{ /if }}
```
# Praxisbeispiele - Verknüpfung mit dem Zahlungsanbieter
Source: https://dokumentation.websale.de/frontend/praxisbeispiele/verknuepfung-zahlungsanbieter
Praxisbeispiele für die Verknüpfung eines Kundenkontos mit dem Konto beim Zahlungsanbieter in WEBSALE: Verwaltung im Kundenkonto mit Setup- und Create-Aktion, Aufheben der Verknüpfung sowie das Opt-in im Bestellablauf.
In diesem Abschnitt finden Sie Praxisbeispiele für die Verknüpfung eines Kundenkontos mit dem Konto beim Zahlungsanbieter. Besteht eine Verknüpfung, muss der Kunde bei Folgebestellungen die Freigabe auf der Seite des Zahlungsanbieters nicht erneut durchlaufen.
Welche Zahlungsarten eine Verknüpfung unterstützen, entscheidet der Zahlungsanbieter. Derzeit unterstützt ausschließlich PayPal Checkout diese Funktion, weshalb die Beispiele die Einbindung des PayPal-SDK zeigen. Die Aktionen selbst sind nicht auf einen bestimmten Zahlungsanbieter festgelegt.
Die Beispiele gehen davon aus, dass die Zahlungsart die ID `paypalCheckout` hat.
***
## Verknüpfung im Kundenkonto verwalten
Die Seite hat zwei Zustände, die über die Funktion [wsAccount.hasPaymentVault() ](/frontend/referenz/module/wsAccount)unterschieden werden: Besteht eine Verknüpfung, wird ein Formular zum Aufheben der Verknüpfung angezeigt. Besteht keine Verknüpfung, wird der PayPal-Button angezeigt. Dieser legt die Verknüpfung in zwei Schritten an: Zunächst holt `PaymentValueSetup` das Setup-Token und anschließend gibt der Kunde die Verknüpfung bei PayPal frei. Zuletzt speichert `PaymentValueCreate` sie.
Weil `PaymentVaultCreate` keinen Antwort-Body liefert, lädt das Beispiel die Seite nach dem Erstellen neu. Erst dadurch liefert `hasPaymentVault()` den neuen Zustand.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ extends "layouts/account_layout.htm" }}
{{ block content_account_main }}
{{ var $ppcData = $wsPayPalCheckout.loadConfigData() }}
{{ var $paymentId = "paypalCheckout"}}
{{ var $paymentVault = $wsAccount.hasPaymentVault($paymentId) }}
{{if not $paymentVault }}
{{ /if }}
PayPal Checkout Vaulting verwalten
{{ var $removeVaultAction = $wsActions.create('PaymentVaultRemove') }}
{{ if $removeVaultAction.globalErrors }}
{{ foreach $err in $removeVaultAction.globalErrors }}
- {{= $err.text | ifNull($err.code) }}
{{ /foreach }}
{{ /if }}
{{ var $paymentVaultSetupAction = $wsActions.create('PaymentVaultSetup') }}
{{ if $paymentVaultSetupAction.globalErrors }}
{{ foreach $err in $paymentVaultSetupAction.globalErrors }}
- {{= $err.text | ifNull($err.code) }}
{{ /foreach }}
{{ /if }}
{{ var $paymentVaultCreateAction = $wsActions.create('PaymentVaultCreate') }}
{{ if $paymentVaultCreateAction.globalErrors }}
{{ foreach $err in $paymentVaultCreateAction.globalErrors }}
- {{= $err.text | ifNull($err.code) }}
{{ /foreach }}
{{ /if }}
{{ if $paymentVault }}
PayPal-Verbindung löschen
{{ else }}
PayPal-Verbindung erstellen
{{ /if }}
{{ /block }}
```
Das Beispiel ist auf Testbarkeit ausgelegt, nicht auf Produktionsreife. Der JavaScript-Teil sollte vor dem Livebetrieb ausgebaut werden: `onError` gibt Fehler nur auf der Konsole aus, und ein Fehlschlag von `PaymentVaultCreate` bleibt dem Kunden verborgen, weil die Seite unmittelbar danach neu geladen wird und die Aktionsfehler des vorangegangenen POST damit verloren gehen.
***
## Verknüpfung im Bestellablauf anbieten
Wenn für die gewählte Zahlungsart bereits eine Verknüpfung besteht, wird die Bestellung direkt darüber bezahlt und der PayPal-Button entfällt. Besteht noch keine Verknüpfung, können Sie dem Kunden anbieten, diese mit der aktuellen Bestellung anzulegen. Dafür genügt das Formularfeld `initPaymentValue` - die Verknüpfung wird dann beim Bestellabschluss automatisch erstellt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
...
{{ var $showPPButton = ($wsCheckout.selectedPayment == "paypalCheckout" or $wsCheckout.selectedPayment == "paypalCheckoutSepa" or $wsCheckout.selectedPayment == "paypalCheckoutPayLater") and $wsCheckout.isValid }}
...
{{ var $ppcVault = $wsCheckout.selectedPayment == "paypalCheckout" and $wsCheckout.hasPaymentVault() }}
{{ $showPPButton = $showPPButton and not $ppcVault}}
...
{{ if $showPPButton }}
...
{{ if not $ppcData }}
Konnte nicht richtig konfigurieren
{{ else }}
PayPal Account für zukünftige Zahlungen speichern
{{ /if }}
...
{{ /if }}
```
Das Feld wird beim Bestellabschluss ausgewertet. Die Verknüpfung entsteht nur, wenn zusätzlich alle folgenden Bedingungen erfüllt sind:
* Der Kunde ist angemeldet.
* Es handelt sich nicht um einen Express-Checkout.
* Die gewählte Zahlungsart ist die reine PayPal-Zahlung, nicht PayPal SEPA oder PayPal PayLater.
* Es besteht noch keine Verknüpfung.
Ist eine dieser Bedingungen nicht erfüllt, wird die Bestellung normal abgeschlossen und die Verknüpfung schlicht nicht angelegt, dafür gibt es keinen Fehlercode. Soll dem Kunden das Anlegen zuverlässig angeboten werden, verwenden Sie den Weg über eine eigene Seite im Kundenkonto, siehe [Verknüpfung im Kundenkonto verwalten](#verknupfung-im-kundenkonto-verwalten).
# Referenz - Übersicht
Source: https://dokumentation.websale.de/frontend/referenz
Komplette Referenz der WEBSALE Template-Sprache: Tags, Anweisungen, Module, Funktionen, Modifier und Aktionen für den Aufbau des Shop-Frontends.
Referenz ist das zentrale Nachschlagewerk für die Template Engine und die Template-Sprache. Hier sind alle relevanten Sprachelemente und Bausteine dokumentiert, die für den Aufbau und die Anpassung des Shop-Frontends auf Basis von Templates benötigt werden – zum Beispiel Tags/Anweisungen, Variablen, Funktionen, Modifier und typische Verwendungsformen.
Diese Referenz richtet sich an Projekte, die das Shop-Frontend mit Templates umsetzen. Soll das Frontend stattdessen über die Storefront API aufgebaut werden (z. B. Headless-Ansatz), ist diese Seite nicht der richtige Einstieg – in diesem Fall sind die Seiten zur [Storefront API](/schnittstellen/storefront-api/storefront-api-basics) relevant.
## Inhaltsverzeichnis
* [Aktionen](/frontend/referenz/aktionen)
* [Anweisungen](/frontend/referenz/anweisungen)
* [Blöcke](/frontend/referenz/blocke)
* [Components](/frontend/referenz/components)
* [Conditions](/frontend/referenz/conditions)
* [Datentypen](/frontend/referenz/datentypen)
* [Funktionen](/frontend/referenz/funktionen) — Globale Template-Funktionen stehen in allen Templates zur Verfügung. Sie werden verwendet, um Werte zu verarbeiten, zu formatieren oder zu prüfen (z. B. Strings anpassen, Zahlen runden, Listen zusammenführen oder Datumswerte vergleichen).
* [Kontrollstrukturen](/frontend/referenz/kontrollstrukturen)
* [Loops](/frontend/referenz/loops)
* [Modifiers](/frontend/referenz/modifiers) — Diese Seite beschreibt die Grundlagen und Schreibweise von Modifiers. Modifiers (auch Filter genannt) werden verwendet, um Werte im Template direkt bei der Ausgabe oder Weiterverarbeitung zu verändern, zu formatieren oder zu prüfen – zum Beispiel Texte anpassen, Zahlen runden oder Listen umwandeln.
* [Operatoren](/frontend/referenz/operatoren)
* [Module](/frontend/referenz/module) — Module sind von WEBSALE vorgegebene, global verfügbare Module (z. B. \$wsAccount). Sie stellen Variablen (Eigenschaften) und Methoden bereit. In der Entwicklung werden sie teilweise auch als View-Module bezeichnet, da sie primär für die Ausgabe (Leseseite) verwendet werden.
* [Variablen](/frontend/referenz/variablen)
# Aktionen - Übersicht
Source: https://dokumentation.websale.de/frontend/referenz/aktionen
Übersicht aller Aktionen der Template-Sprache: Eingaben des Nutzers für Warenkorb, Login, Registrierung und mehr verarbeiten und Ergebnisse auswerten.
Aktionen sind das Bindeglied zwischen dem, was ein Benutzer im Shop macht, und dem, was der Shop daraufhin ausführt. Ob ein Kunde ein Produkt in den Warenkorb legt, sich registriert oder einloggt - hinter jedem dieser Vorgänge steckt eine Aktion.
Aktionen nehmen die Eingaben des Benutzers entgegen, verarbeiten sie im Hintergrund und geben dem Frontend zurück, ob alles geklappt hat oder ein Fehler aufgetreten ist.
***
## Grundprinzip
Der Shop stellt eine Reihe vordefinierter Aktionen bereit. Diese sind vom System vorgegeben und können nicht frei benannt werden. Jede Aktionen hat einen festen Namen, zum Beispiel `BasketItemAdd` (Produkt in den Warenkorb legen), `Login` (Benutzer einloggen) oder `AccountRegister` (neues Konto anlegen).
Aktionen können auf drei Arten ausgeführt werden:
* Über ein Formular - der häufigste Fall. Der Benutzer füllt ein Formular aus und sendet es ab.
* Über einen Link - für Aktionen ohne Benutzereingaben, zum Beispiel das Ausloggen.
* Per AJAX - wenn die Seite nach der Ausführung nicht neu geladen werden soll.
Unabhängig davon, wie eine Aktion ausgeführt wird, läuft im Hintergrund immer derselbe Prozess ab: Der Shop empfängt die Anfrage, verarbeitet sie und gibt zurück, ob die Aktion erfolgreich war oder ein Fehler aufgetreten ist.
Einige Aktionen Verhalten sich abweichend und geben statt einer neuen Seite direkt Daten zurück, zum Beispiel als JSON im Rahmen des Checkouts. Dieses abweichende Verhalten ist bei den betreffenden Aktionen jeweils dokumentiert.
***
## Aktionen vorbereiten
Bevor eine Aktion in einem Template genutzt werden kann, muss ein sogenanntes Aktionsobjekt erstellt werden. Man kann es sich wie einen Behälter vorstellen, der alles enthält, was für die Ausführung der Aktion benötigt wird und nach dem Absenden auch die Rückmeldung des Shops enthält.
Das Aktionsobjekt wird mit [\$wsActions.create()](/frontend/referenz/module/wsactions#%24wsactions-create) erstellt, wobei der Name der gewünschten Aktion übergeben wird:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myAction = $wsActions.create("BasketItemAdd") }}
```
Optional kann hier bereits die Zielseite, auf die nach erfolgreicher Ausführung der Aktion weitergeleitet wird, mitgegeben werden:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myAction = $wsActions.create("BasketItemAdd", target=$wsViews.viewUrl('basket.htm')) }}
```
Das Objekt löst dabei noch nicht aus, es bereitet lediglich die Aktion vor. Die Aktion selbst wird erst ausgeführt, wenn der Benutzer das Formular absendet, auf einen Link klickt oder eine AJAX-Anfrage abgesendet wird.
Nach der Ausführung befüllt der Shop das Aktionsobjekt automatisch mit Rückmeldungen. Im Template kann dann über die Variable `$myAction` darauf zugegriffen werden, zum Beispiel mit `$myAction.success` oder `$myAction.errors`. Eine vollständige Beschreibung aller verfügbaren Eigenschaften findet sich in der [\$wsActions Modulreferenz](/frontend/referenz/module/wsactions).
| **Eigenschaft** | **Beschreibung** |
| - | - |
| `$action.id` | Die ID der Aktion, die im Formular benötigt wird, damit der Shop weiß, was ausgeführt werden soll. |
| `$action.csrf` | Ein Sicherheits-Token, das jede Anfrage absichert (mehr dazu [hier](#3-2-1-csrf-schutz)). |
| `$action.success` | Ist `true`, wenn die Aktion erfolgreich ausgeführt wurde. |
| `$action.error` | Ist `true`, wenn ein Fehler aufgetreten ist. |
| `$action.errors` | Eine Liste aller aufgetretenen Fehler mit Fehlercode, betroffenem Feld und optionalem Detail. |
| `$action.params` | Die zuletzt eingegebenen Werte. Nützlich, um ein Formular bei einem Fehler vorausgefüllt anzuzeigen, damit der Benutzer nicht alles neu eingeben muss. |
***
## Aktionen ausführen
### Ausführung über Formulare
Der häufigste Weg, eine Aktion auszuführen, ist ein HTML-Formular. Das vorbereitete Aktionsobjekt wird in das Formular eingebunden und die Aktion wird ausgeführt, sobald der Benutzer das Formular absendet.
Das Formular wird immer an die URL der aktuellen Seite gesendet, damit der Shop nach der Ausführung dieselbe Seite neu aufbauen und die Rückmeldung anzeigen kann:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
```
### Tags - mehrere Formulare derselben Aktionsart unterscheiden
Wenn auf einer Seite mehrere Formulare derselben Aktionsart vorkommen, zum Beispiel ein “In den Warenkorb”-Button in jeder Produktbox einer Kategorieseite, teilen sich alle diese Formulare standardmäßig dieselben Rückmeldungen. Das bedeutet: Tritt bei einem Produkt ein Fehler auf, würden alle Formulare auf der Seite diesen Fehler anzeigen.
Mit einem Tag lässt sich jede Aktion eindeutig unterscheiden. Als Tag eignet sich zum Beispiel die Produkt-ID:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $action = $wsActions.create("BasketItemAdd", tag=$product.id) }}
```
Der Shop erzeugt daraus eine eindeutige ID im Format `BasketItemAdd:42` (wobei `42` in diesem Beispiel die Produkt-ID wäre). Dadurch erhält jedes Produkt ein eigenes Aktionsobjekt und Fehler erscheinen nur beim betreffenden Formular.
Bei einigen Aktionen, insbesondere im Checkout, wird der Tag genutzt, um den Adresstyp direkt im Aktionsnamen festzulegen:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $commitBillAction = $wsActions.create("CheckoutCommitDraftAddress:bill") }}
{{ var $commitShippingAction = $wsActions.create("CheckoutCommitDraftAddress:shipping") }}
```
### Aktionen absichern
Aktionen können auf zwei Arten gegen unerlaubte Zugriffe geschützt werden - durch einen CSRF-Token, der bei jeder Aktion Pflicht ist und optional durch ein Captcha.
### CSRF-Schutz
CSRF (`Cross-Site Request Forgery`) bezeichnet einen Angriff, bei dem eine externe Website im Namen eines eingeloggten Benutzers unbemerkt Anfragen an den Shop sendet, zum Beispiel um eine Bestellung auszulösen oder Kontodaten zu ändern. Der CSRF-Schutz verhindert, dass solche Anfragen vom Shop akzeptiert werden.
Dazu wird für jede Benutzersitzung ein einmaliger CSRF-Token erzeugt. Weil der Token an die aktuelle Sitzung gebunden ist, kann eine fremde Website ihn nicht kennen und die Aktion damit nicht unbemerkt auslösen. Der Token steht direkt am Aktionsobjekt zur Verfügung und wird so eingebunden:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
```
### Captcha-Schutz
Für bestimmte Aktionen, zum Beispiel die Registrierung oder ein Kontaktformular, kann zusätzlich ein Captcha aktiviert werden. Ein Captcha ist eine Sicherheitsabfrage, die sicherstellt, dass das Formular von einem echten Menschen ausgefüllt wird und nicht von einem automatisierten Bot.
Ist der Captcha-Schutz für eine Aktion aktiv, wird die Aktion nur ausgeführt, wenn der Benutzer das Captcha erfolgreich gelöst hat. Schlägt die Prüfung fehl, wird die Aktion nicht ausgeführt.
Damit der Schutz greift, sind zwei Voraussetzungen nötig:
1. Die Aktion muss in der [Shop-Konfiguration](/konfiguration/security-sicherheitsregeln) unter `security.actionGuard` für den Captcha-Schutz eingetragen sein.
2. Das Captcha-Widget muss im Template des zugehörigen Formulars eingebunden sein. Mehr dazu [hier](https://websale.atlassian.net/wiki/x/AwAhdw).
Wird eine Aktion über einen Bestätigungslink per E-Mail ausgeführt (Opt-In-Link), findet keine Captcha-Prüfung statt. In diesem Fall gilt der Link selbst als Nachweis, dass ein Mensch gehandelt hat.
### Ausführung über Links
Aktionen ohne Benutzereingaben, zum Beispiel das Ausloggen oder das Entfernen eines Artikels aus dem Warenkorb, können über einen Link ausgelöst werden, ohne das ein Formular nötig ist.
Dazu wird mit [\$wsActions.url()](/frontend/referenz/module/wsactions#\$wsactions-url) eine URL erzeugt. Die Methode erwartet drei Angaben: den Aktionsnamen, die Zielseite nach der Ausführung und optionale Parameter als Liste. Sind keine optionalen Parameter nötig, wird eine leere Liste `{}` übergeben:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Ausloggen
```
### Ausführung per AJAX
Standardmäßig wird nach dem Absenden eines Formulars die gesamte Seite neu geladen. Manchmal ist das aber nicht gewünscht, zum Beispiel wenn nur ein kleiner Bereich der Seite aktualisiert werden soll, ohne das der Benutzer einen sichtbaren Neuladevorgang erlebt.
In solchen Fällen kann die Aktion per AJAX ausgeführt werden. Dabei werden die Daten im Hintergrund an den Shop geschickt und die Antwort (Erfolg oder Fehler) direkt per JavaScript verarbeitet, ohne die Seite neu zu laden. CSRF-Schutz ist dabei genauso erforderlich wie bei Formularen, der Token ist über [\$wsActions.csrfToken](/frontend/referenz/module/wsactions#\$wsactions-current-csrf) abrufbar.
Ein typisches Anwendungsbeispiel:\
Der Benutzer legt ein Produkt in den Warenkorb und nur der Warenkorb-Zähler im Header aktualisiert sich, der Rest der Seite bleibt unverändert.
```javascript theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
$.post("{{= $wsViews.viewUrl('ajax/actionResponse.json') }}", {
"wscsrf": "{{= $wsActions.csrfToken }}",
"wsact": "BasketItemAdd",
"productId": "12345",
"quantity": 2
}, function(data) {
if (data.success) {
// Aktion erfolgreich – z.B. Warenkorb-Zähler im Header aktualisieren
} else {
// Fehler anzeigen
console.log(data.errors);
}
});
```
### Mehrere Aktionen gleichzeitig ausführen
Manchmal sollen mit einem einzigen Klick auf “Absenden” mehrere Aktionen nacheinander ausgeführt werden. Ein typisches Beispiel ist der letzte Schritt im Checkout, bei dem die Rechnungsadresse und die Lieferadresse bestätigt und die Bestellung abgeschlossen werden.
Dafür wird statt des normalen `wsact`-Feldes das Feld `wsmultiact` verwendet, und zwar einmal pro Aktion. `wsact` und `wsmultiact` können nicht im selben Formular kombiniert werden.
Die Aktionen werden in der Reihenfolge ausgeführt in der die `wsmultiact`-Felder im Formular aufgelistet sind.\\
#### Felder einer Aktion zuordnen
Weil mehrere Aktionen im selben Formular Felder entgegennehmen, muss jedes Feld klar einer bestimmten Aktion zugeordnet werden. Das geschieht durch ein Präfix vor dem Feldnamen, getrennt durch `|`. Im Template sieht es so aus:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
```
Das bedeutet: Das Feld `addressType` mit dem Wert `bill` gehört zur Aktion `$commitBillAction`.\\
#### Fehler einer Aktion soll die nächste stoppen
Standardmäßig werden alle Aktionen ausgeführt, auch wenn eine davon fehlschlägt. Soll eine fehlgeschlagene Aktion die nachfolgende abbrechen, kann der Parameter `wsmultiactabortonerror` auf `on` gesetzt werden:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
```
#### Fehler einer Aktion ignorieren
`wsmultiactignoreerror` können einzelne Aktionen als unkritisch markiert werden. Schlägt eine so markierte Aktion fehl, wird das nicht als fataler Fehler behandelt. Der Parameter kann mehrfach angegeben werden, einmal pro Aktion:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
```
Einen Fehler zu ignorieren wirkt sich auf zwei Situationen aus:
* **Weiterleitung trotz Fehler** \
Standardmäßig bleibt der Nutzer bei einem Fehler auf der aktuellen Seite und wird nicht auf die in `wstarget` angegebene Zielseite weitergeleitet. Ist die fehlgeschlagene Aktion über `wsmultiactignoreerror` markiert, findet die Weiterleitung dennoch statt.
* **Folgeaktionen laufen weiter** \
Ist zusätzlich `wsmultiactabortonerror=on` gesetzt, würde ein Fehler normalerweise alle nachfolgenden Aktionen abbrechen. Aktionen, die über `wsmultiactignoreerror` markiert sind, lösen diesen Abbruch nicht aus - die Ausführung wird fortgesetzt.
**Beispiel: Checkout-Abschluss**\
Das folgende Beispiel zeigt den letzten Schritt eines Checkouts. Mit einem Klick auf “Jetzt bestellen” werden drei Aktionen nacheinander ausgeführt:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $commitBillAction = $wsActions.create("CheckoutCommitDraftAddress:bill") }}
{{ var $commitShippingAction = $wsActions.create("CheckoutCommitDraftAddress:shipping") }}
{{ var $checkoutConfirm = $wsActions.create("CheckoutConfirm") }}
```
Ausführungsreihenfolge des Beispiels:
1. `CheckoutCommitDraftAddress:bill` - Rechnungsadresse übernehmen
2. `CheckoutCommitDraftAddress:shipping`- Lieferadresse übernehmen
3. `CheckoutConfirm` - Bestellung abschließen
### Ergebnis der Ausführung
#### Erfolg
War die Aktion erfolgreich, ist `$myAction.success` gleich `true`. In diesem Fall kann eine Erfolgsmeldung angezeigt oder der Benutzer über `wstarget` auf eine andere Seite weitergeleitet werden.
#### Fehler
Schlägt die Aktion fehl, zum Beispiel weil ein Pflichtfeld fehlt oder eine E-Mail-Adresse ungültig ist, ist `$myAction.error` gleich `true`. Die Fehlermeldungen sollten im Template ausgegeben werden, damit der Benutzer weiß, was korrigiert werden muss:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $myAction.error }}
Bitte korrigiere folgende Angaben:
{{ foreach $error in $myAction.errors }}
{{ if $error.text }}
- {{= $error.text }} ({{= $error.field }}){{ if $error.subCode }} – {{= $error.subCode }}{{ /if }}
{{ else }}
- {{= $error.code }} ({{= $error.field }}){{ if $error.subCode }} – {{= $error.subCode }}{{ /if }}
{{ /if }}
{{ /foreach }}
{{ /if }}
```
Welche Fehlercodes eine bestimmte Aktion zurückgeben kann, ist in der jeweiligen Aktionsdokumentation ausgeführt. Eine Erklärung aller Fehlereigenschaften findet sich in der [\$wsActions Modulreferenz](/frontend/referenz/module/wsactions).
### Weiterleitung
Nach einer erfolgreich ausgeführten Aktion kann der Benutzer auf eine Zielseite weitergeleitet werden. Das verhindert außerdem, dass ein Seiten-Reload das Formular erneut absendet. Mehr dazu [hier](#2-aktionen-vorbereiten).
***
## Aktionsübersicht
Eine vollständige Übersicht aller verfügbaren Aktionen findet sich in den jeweiligen Themenbereichen:
* [Account](/frontend/referenz/aktionen/account)
* [Basket](/frontend/referenz/aktionen/basket)
* [Checkout](/frontend/referenz/aktionen/checkout)
* [Consent](/frontend/referenz/aktionen/consent)
* [DirectOrder](/frontend/referenz/aktionen/directorder)
* [Inquiry](/frontend/referenz/aktionen/inquiry)
* [Inventory](/frontend/referenz/aktionen/inventory)
* [Newsletter](/frontend/referenz/aktionen/newsletter)
* [ProductRating](/frontend/referenz/aktionen/productrating)
* [Session](/frontend/referenz/aktionen/session)
* [Stores](/frontend/referenz/aktionen/stores)
* [TestMode](/frontend/referenz/aktionen/testmode)
* [Voucher](/frontend/referenz/aktionen/voucher)
* [WatchList](/frontend/referenz/aktionen/watchlist)
# Account
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/account
Aktionen für Kundenkonten: Konten und Adressen anlegen, Anmeldedaten und Passwörter ändern sowie B2B-Mitarbeiterkonten und Berechtigungen verwalten.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich Kundenkonto beschrieben. Mithilfe dieser Aktionen können Sie Kundenkonten anlegen und verwalten, Anmeldedaten und Passwörter ändern sowie Adressen pflegen. Im B2B-Bereich ist zudem die Verwaltung von Mitarbeiterkonten und Berechtigungsgruppen möglich.
## Grundkonzept
**Abgrenzung der Möglichkeiten im Kundenkonto:**
* Daten lesen (Adressen, Profil, Login-Status) - dies erfolgt nicht über Aktionen, sondern über das Modul [\$wsAccount](/frontend/referenz/module/wsAccount).
* **Strukturelle Einstellungen** (Adressfelder, Kundendatenfelder, B2B-Konfiguration) werden in der [Konfiguration](/konfiguration) festgelegt.
* Diese Seite beschreibt ausschließlich die Aktionen, die Konto-, Adress- und Berechtigungsdaten verändern.
### Grundlagen: Aufbau einer Aktion
Jede Aktion wird mit `$wsActions.create("")` erzeugt und in ein Formular eingebunden. Pflichtfelder jedes Formulars sind `wsact` (ID der Aktion) und `wscsrf` (CSRF-Token). Details siehe [Aktionen - Übersicht](/frontend/referenz/aktionen).
### Adressen: Typen, Standard und Sichtbarkeit
Adressen haben einen Typ (`bill` = Rechnungsadresse, `delivery` = Lieferadresse). Die erste Adresse eines Typs wird automatisch zur Hauptadresse dieses Typs. Über `SetMainAddress`, `SetDefaultBillAddress` und `SetDefaultDeliveryAddress` lassen sich Standardadressen festlegen, die im Checkout vorausgewählt werden.
Im B2B-Kontext besitzt jede Adresse zusätzlich eine Sichtbarkeit: privat (nur für ein Mitarbeiterkonto) oder firmenweit freigegeben. Welcher Wert beim Anlegen vorausgewählt ist, steuert `defaultAddressVisibility` (siehe `UpdateSubAccount`). Wem eine Adresse gehört, steuert das Feld `addressOwnerMemberId` (siehe `AddressCreate`).
### B2B: Mitarbeiterkonten & Berechtigungsgruppen
Diese Funktionen stehen ausschließlich für Firmenkonten im B2B-Bereich zur Verfügung. Für alle zugehörigen Aktionen sind Admin-Rechte erforderlich. Eine Berechtigungsgruppe bündelt verschiedene Rechte und Einschränkungen, beispielsweise erlaubte Zahlungsarten, Budgetgrenzen oder gesperrte Seiten. Der typische Ablauf sieht wie folgt aus:
1. Gruppe anlegen → `CreatePrivilegeGroup`
2. Rechte/Einschränkungen der Gruppe setzen → `UpdatePrivileges`
3. Gruppe einem Mitarbeiterkonto zuweisen → `UpdateSubAccount` (`privilegeGroupId`)
Mitarbeiterkonten selbst werden über `SubAccountCreate`, `UpdateSubAccount` und `SubAccountDelete` verwaltet. Die in der Gruppe gesetzten Budgetgrenzen werden im Frontend am Mitarbeiterkonto schreibgeschützt über [\$wsAccount.paymentLimit](/frontend/referenz/module/wsAccount) und `$wsAccount.paymentLimitPerOrder` gelesen.
***
## Aktionen im Überblick
**Konto**
| **Aktion** | **Beschreibung** |
| - | - |
| `AccountRegister` | Erstellt ein neues Kundenkonto. |
| `AccountActivate` | Aktiviert ein bestehendes Kundenkonto über eine E-Mail-Adresse. |
| `AccountActivateOptIn` | Aktiviert ein bestehendes Kundenkonto per Opt-In-Token. |
| `EmailVerify` | Verifiziert eine E-Mail-Adresse per Double-Opt-In. |
| `AccountDelete` | Löscht den Account des eingeloggten Benutzers. |
| `AccountDeleteOptIn` | Bestätigt die Löschung eines Kundenkontos per Opt-In-Token. |
**Anmeldung & Passwort**
| **Aktion** | **Beschreibung** |
| - | - |
| `Login` | Meldet einen Benutzer an. |
| `Logout` | Meldet einen eingeloggten Benutzer ab. |
| `UnlockLogin` | Entsperrt einen gesperrten Login-Zugang. |
| `PasswordForgotten` | Sendet eine Passwort-vergessen-E-Mail. |
| `ResetPassword` | Setzt das Passwort eines Benutzerkontos neu. |
| `CheckPasswordStrength` | Prüft die Stärke eines eingegebenen Passworts in Echtzeit per AJAX. |
**Konto- & Kontaktdaten**
| **Aktion** | **Beschreibung** |
| - | - |
| `EmailUpdate` | Ändert die hinterlegte E-Mail-Adresse eines Benutzerkontos. |
| `EmailUpdateOptIn` | Bestätigt die Änderung der E-Mail-Adresse per Opt-In-Token. |
| `accountDisplayNameUpdate` | Ändert den Anzeigenamen eines Kundenkontos. |
| `AccountSetCustomerData` | Setzt oder aktualisiert benutzerdefinierte Kundendaten. |
**Adressen**
| **Aktion** | **Beschreibung** |
| - | - |
| `AddressCreate` | Erstellt eine neue Adresse für den eingeloggten Benutzer. |
| `AddressUpdate` | Bearbeitet eine bestehende Adresse des eingeloggten Benutzers. |
| `AddressDelete` | Löscht eine Adresse des eingeloggten Benutzers. |
| `SetMainAddress` | Legt eine Adresse als Hauptadresse fest. |
| `SetDefaultBillAddress` | Legt eine Adresse als Standard-Rechnungsadresse fest. |
| `SetDefaultDeliveryAddress` | Legt eine Adresse als Standard-Lieferadresse fest. |
| `RemoveDefaultBillAddress` | Entfernt die gesetzte Standard-Rechnungsadresse. |
| `RemoveDefaultDeliveryAddress` | Entfernt die gesetzte Standard-Lieferadresse. |
**Kreditkarten**
| **Aktion** | **Beschreibung** |
| - | - |
| `CreditCardDelete` | Löscht eine gespeicherte Kreditkarte aus dem Kundenkonto. |
**Gastkonto**
| **Aktion** | **Beschreibung** |
| - | - |
| `GuestRegister` | Erstellt aus einem Gast-Checkout ein vollwertiges Kundenkonto (E-Mail aus Checkout-Daten). |
| `SaveGuestDataToUser` | Erstellt aus einem Gast-Checkout ein vollwertiges Kundenkonto. |
**B2B – Mitarbeiterkonten** (Admin-Rechte erforderlich)
| **Aktion** | **Beschreibung** |
| - | - |
| `SubAccountCreate` | Legt ein neues Mitarbeiterkonto an und sendet eine E-Mail mit dem Link zum Setzen des Passworts. |
| `UpdateSubAccount` | Aktualisiert die Einstellungen eines Mitarbeiterkontos. |
| `SubAccountDelete` | Löscht ein bestehendes Mitarbeiterkonto. |
| `AcceptInvitation` | Nimmt eine Einladung zu einem Firmenkonto per Double-Opt-In an. |
**B2B – Berechtigungsgruppen** (Admin-Rechte erforderlich)
| **Aktion** | **Beschreibung** |
| - | - |
| `CreatePrivilegeGroup` | Legt eine neue Berechtigungsgruppe an. |
| `UpdatePrivileges` | Erstellt oder aktualisiert eine Berechtigungsgruppe mit definierten Rechten. |
| `DeletePrivilegeGroup` | Löscht eine bestehende Berechtigungsgruppe. |
***
## Konto-Lebenszyklus
### AccountRegister
Mit dieser Aktion wird ein neues Kundenkonto angelegt. Dabei gibt der Benutzer seine E-Mail-Adresse sowie ein Passwort an. Nach erfolgreicher Registrierung ist der Kunde automatisch eingeloggt und erhält eine neue Session.
**Anwendungsbeispiel**\
Nutzbar auf einer Registrierungsseite, auf der neue Kunden ein Konto erstellen können, um beispielsweise ihre Bestellhistorie einzusehen oder Adressen zu verwalten.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `email` | Identifier des Benutzer-Accounts (standardmäßig die E-Mail-Adresse). |
| `password` | Passwort des Benutzer-Accounts. |
| `passwordRepeat` | Erneute Eingabe des Passworts - muss mit `password` übereinstimmen. |
**Fehlercodes**
| **Code** | **Beschreibung** |
| - | - |
| `missingId` | Parameter `email` ist leer. |
| `missingPassword` | Parameter `password` ist leer. |
| `passwordMismatch` | Parameter `password` und `passwordRepeat` sind nicht identisch. |
| `emailCheckFailed` | Parameter `email` enthält eine ungültige E-Mail-Adresse. |
| `passwordCheckFailed` | Passwort erfüllt nicht die erforderlichen Richtlinien. |
| `accountAlreadyExists` | Es existiert bereits ein Account mit der angegebenen `email`. |
| `duplicateAccountFound` | Zu den angegebenen Daten existiert bereits ein Kundenkonto (Dublettenprüfung). |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie die Aktion erstellt und in ein Formular eingebunden wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionAccountRegister = $wsActions.create("AccountRegister") }}
```
***
### AccountActivate
Mit dieser Aktion aktiviert ein Kunde ein bereits angelegtes Kundenkonto, beispielsweise ein importiertes Konto, und vergibt dabei sein Passwort. Das Konto wird über die Kundennummer gefunden. Die Aktion steht nur zur Verfügung, wenn die Kontoaktivierung in der Konfiguration aktiviert ist. Ist eim Opt-In vorgesehen, erhält der Kunde eine E-Mail mit einem Bestätigungslink. Die Aktivierung wird dann mit der Aktion `AccountActivateOptIn` abgeschlossen. Andernfalls wird das Konto sofort aktiviert und der Kunde direkt eingeloggt.
**Anwendungsbeispiel**\
Nutzbar auf einer Aktivierungsseite, auf der Kunden mit bestehender Kundennummer ihr Konto freischalten und ein Passwort festlegen.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `customerNumber` | Kundennummer des bestehenden Kontos. |
| `email` | E-Mail-Adresse des Kunden. Pflichtangabe, wenn Mitarbeiterkonten aktiviert sind. Bei aktivem Opt-In wird der Bestätigungslink an diese Adresse gesendet. |
| `password` | Neues Passwort für das Konto. |
| `passwordRepeat` | Erneute Eingabe des Passworts, muss mit `password` übereinstimmen. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `disabled` | Die Kontoaktivierung ist in der Konfiguration nicht aktiviert. |
| `missingId` | Parameter `email` ist leer (nur bei aktivierten Mitarbeiterkonten). |
| `missingCustomerNumber` | Parameter `customerNumber` ist leer. |
| `missingPassword` | Parameter `password` ist leer. |
| `passwordMismatch` | Parameter `password` und `passwordRepeat` sind nicht identisch. |
| `emailCheckFailed` | Parameter `email` enthält eine ungültige E-Mail-Adresse. |
| `passwordCheckFailed` | Passwort erfüllt nicht die erforderlichen Richtlinien. |
| `accountNotFound` | Zur angegebenen `customerNumber` existiert kein Konto. |
| `accountAlreadyActivated` | Das Konto ist bereits aktiviert. Das ist der Fall, wenn es ein Passwort besitzt, Mitarbeiterkonten hat oder bereits ein Einladungslink versendet wurde. |
| `accountAlreadyExists` | Für die angegebene E-Mail-Adresse existiert bereits ein Konto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isAccountVerified](/frontend/referenz/module/wsAccount#%24wsaccount-isaccountverified)
**Beispiel** das zeigt, wie die Aktion erstellt und in ein Formular eingebunden wird, über das der Kunde sein bestehendes Konto mit Kundennummer und neuem Passwort aktiviert.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionAccountActivate = $wsActions.create("AccountActivate") }}
```
***
### AccountActivateOptIn
Mit dieser Aktion wird ein bestehendes Kundenkonto per Opt-In-Token aktiviert. Der Token wird dabei über einen Link in einer Bestätigungs-E-Mail an den Benutzer übermittelt.
**Anwendungsbeispiel**\
Nutzbar auf der Bestätigungsseite, auf die der Kunde nach Klick auf den Opt-In-Link in der Registrierungs-E-Mail weitergeleitet wird.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `actionNotAllowed` | Es wurde kein gültiger Opt-In-Token übergeben oder der Link ist abgelaufen. |
| `accountNotFound` | Das zu aktivierende Konto wurde nicht gefunden. |
| `accountAlreadyActivated` | Das Konto ist bereits aktiviert. |
| `accountAlreadyExists` | Für die E-Mail-Adresse existiert bereits ein Konto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isAccountVerified](/frontend/referenz/module/wsAccount#%24wsaccount-isaccountverified)
**Beispiel** das zeigt, wie nach erfolgreicher Ausführung der Aktion eine Bestätigungsmeldung angezeigt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current.name == "AccountActivateOptIn" and $wsActions.current.success }}
Account wurde aktiviert.
{{ /if }}
```
***
### EmailVerify
Mit dieser Aktion wird eine E-Mail-Adresse per Double-Opt-In-Verfahren verifiziert. Nach der Registrierung erhält der Kunde eine Bestätigungs-E-Mail. Durch Klicken auf den darin enthaltenen Link wird die Verifizierung auf der Shop-Seite ausgeführt.
**Anwendungsbeispiel**\
Nutzbar auf der Bestätigungsseite, auf die der Kunde nach Klick auf den Verifizierungslink in der Registrierungs-E-Mail weitergeleitet wird.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `actionNotAllowed` | Kein gültiger Double-Opt-In-Token vorhanden. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie nach erfolgreichem Klick auf den Bestätigungslink eine Erfolgsmeldung ausgegeben wird und bei einem ungültigen Token ein entsprechender Hinweis erscheint.
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current.name == "EmailVerify" }}
{{ if $wsActions.current.success }}
E-Mail-Adresse wurde verifiziert.
{{ else }}
E-Mail-Adresse konnte nicht verifiziert werden.
{{ /if }}
{{ /if }}
```
***
### AccountDelete
Mit dieser Aktion wird der Account des aktuell eingeloggten Benutzers unwiderruflich gelöscht. Wenn in der Konfiguration das Double-Opt-In-Verfahren für die Kontolöschung aktiviert ist, erhält der Kunde stattdessen eine E-Mail mit einem Bestitägungslink. Die Löschung wird dann erst mit der Aktion `AccountDeleteOptIn` ausgeführt.
**Anwendungsbeispiel**\
Nutzbar auf einer Account-Verwaltungsseite, auf der eingeloggte Kunden ihr Konto auf Wunsch selbst löschen können.
**Fehlercodes**
| **Code** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `noPermission` | Der Benutzer ist ein Mitarbeiterkonto ohne Admin-Rechte. Nur der Administrator des Firmenkontos darf das Konto löschen. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie die Aktion erstellt wird und über einen Bestätigungs-Button ausgelöst wird.
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionAccountDelete = $wsActions.create("AccountDelete") }}
```
***
### AccountDeleteOptIn
Mit dieser Aktion wird die Löschung eines Kundenkontos per Opt-In-Token bestätigt. Der Token wird über einen Link in einer Bestätigungs-E-Mail an den Benutzer übermittelt.
**Anwendungsbeispiel**\
Nutzbar auf der Bestätigungsseite, auf die der Kunde nach Klick auf den Opt-In-Link in der Löschungs-E-Mail weitergeleitet wird.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `actionNotAllowed` | Es wurde kein gültiger Opt-In-Token übergeben oder das zugehörige Konto existiert nicht mehr. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie nach erfolgreicher Ausführung der Aktion eine Bestätigungsmeldung angezeigt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current.name == "AccountDeleteOptIn" and $wsActions.current.success }}
Account wurde gelöscht.
{{ /if }}
```
***
## Anmeldung & Passwort
### Login
Mit dieser Aktion wird ein Benutzer mit seinen Zugangsdaten angemeldet. Nach erfolgreicher Anmeldung erzeugt der Shop eine neue Session. Bei mehrfach fehlgeschlagenen Anmeldeversuchen wird der Login gesperrt. Der Kunde wird per E-Mail über die Sperre informiert und erhält einen Entsperrlink (siehe `UnlockLogin`).
**Anwendungsbeispiel**\
Nutzbar auf der Login-Seite, auf der Kunden sich mit E-Mail-Adresse und Passwort in ihr Konto einloggen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `id` | Identifier des Benutzer-Accounts (standardmäßig die E-Mail-Adresse). |
| `password` | Passwort des Benutzer-Accounts. |
**Fehlercodes**
| **Code** | **Beschreibung** |
| - | - |
| `missingId` | Parameter `id` ist leer. |
| `missingPassword` | Parameter `password` ist leer. |
| `emailCheckFailed` | Parameter `id` enthält eine ungültige E-Mail-Adresse. |
| `loginBlocked` | Zu viele ungültige Loginversuche. |
| `invalidCredentials` | Ungültiger Loginversuch - `id` oder `password` sind nicht korrekt. Der Code wird auch ausgegeben, wenn das Konto für den aktuellen Subshop nicht freigegeben ist. |
| `ipAddressBlocked` | Von der IP-Adresse des Benutzers sind derzeit keine weiteren Anmeldungen möglich. |
| `duplicatePendingReview` | Das Konto befindet sich noch in der Duplettenprüfung und kann noch nicht zur Anmeldung genutzt werden. |
| `passwordNotSet` | Für das Mitarbeiterkonto wurde noch kein Passwort vergeben. Tritt nur bei aktivierten Mitarbeiterkonten auf. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das ein Login-Formular mit E-Mail und Passwort sowie einer allgemeinen Fehlerausgabe bei ungültigen Angaben erstellt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionLogin = $wsActions.create("Login") }}
```
***
### Logout
Mit dieser Aktion wird ein eingeloggter Benutzer abgemeldet. Dabei werden die Kundendaten der Sitzung zurückgesetzt, gespeicherte Auto-Login-Daten entfernt und eine neue Sitzung erzeugt. Wenn kein Benutzer eingeloggt ist, passiert nichts.
**Anwendungsbeispiel**\
Nutzbar als Logout-Button im Header oder auf der Account-Übersichtsseite.
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie die Aktion über einen einfachen Link ausgelöst wird, der den Benutzer nach dem Logout auf eine definierte Seite weiterleitet.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Ausloggen
```
***
### UnlockLogin
Mit dieser Aktion wird ein Login-Zugang entsperrt, der aufgrund zu vieler fehlgeschlagener Anmeldeversuche gesperrt wurde. Die Aktion kann sowohl von einem eingeloggten Benutzer als auch über einen Opt-In-Token ausgeführt werden.
**Anwendungsbeispiel**\
Nutzbar, wenn ein Kunde nach mehreren Fehleingaben aus seinem Konto ausgesperrt wurde und einen Entsperrlink per E-Mail erhalten hat.
**Fehlercodes**
| **Code** | **Beschreibung** |
| - | - |
| `unauthorized` | Der Benutzer ist nicht eingeloggt oder es wurde kein gültiger Opt-In-Token übergeben. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
* [\$wsAccount.isAccountVerified](/frontend/referenz/module/wsAccount#%24wsaccount-isaccountverified)
**Beispiel** das zeigt, wie nach erfolgreicher Ausführung der Aktion eine Bestätigungsmeldung angezeigt wird. Die Aktion selbst wird typischerweise über einen Opt-In-Link in einer E-Mail ausgelöst und benötigt kein Formular.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current.name == "UnlockLogin" and $wsActions.current.success }}
Account wurde entsperrt
{{ /if }}
```
***
### PasswordForgotten
Mit dieser Aktion wird eine Passwort-vergessen-E-Mail an die angegebene E-Mail-Adresse gesendet. Diese enthält einen Opt-In-Link, der die Ausführung der Aktion `ResetPassword` ermöglicht. Die Aktion setzt das Passwort jedoch nicht selbst zurück.
**Anwendungsbeispiel**\
Nutzbar auf einer “Passwort vergessen”-Seite, auf der Kunden ihre E-Mail-Adresse eingeben, um einen Wiederherstellungslink zu erhalten.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `email` | E-Mail-Adresse des Benutzerkontos, an die der Opt-In-Link gesendet wird. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingEmail` | Parameter `email` ist leer. |
| `emailCheckFailed` | Parameter `email` enthält keine gültige E-Mail-Adresse. |
| `passwordRecoveryFailed` | Es existiert kein Benutzerkonto zu der angegebenen E-Mail-Adresse. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
**Beispiel,** das ein Formular erstellt, über das der Kunde seine E-Mail-Adresse eingibt und nach erfolgreicher Ausführung eine Bestätigung erhält.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionPasswordForgotten = $wsActions.create("PasswordForgotten") }}
```
***
### ResetPassword
Mit dieser Aktion wird das Passwort des ausgewählten Benutzerkontos zurückgesetzt. Standardmäßig gilt die Aktion für den aktuell eingeloggten Benutzer. Wird ein Opt-In-Token mitgesendet, gilt sie für den mit dem Token verknüpften Benutzer. Ohne Opt-In-Token wird der Benutzer nach erfolgreicher Ausführung automatisch ausgeloggt, sofern in der Konfiguration die Option `autoLogout` aktiviert ist (Standard). Ob das bisherige Passwort abgefragt wird, wird über die Optionen von `actions.resetPassword` gesteuert (siehe [actions - Anmeldung & Registrierung](/konfiguration/actions-fehlertexte-e-mails/actions-anmeldung-registrierung)).
Das neue Passwort muss sich vom bisherigen Passwort unterscheiden. Der Opt-In-Token aus der E-Mail "Passwort vergessen" ist nur einmal gültig. Nach der Änderung beendet der Shop alle aktiven Sessions des Kontos.
**Anwendungsbeispiel**\
Nutzbar auf der Seite, auf die der Kunde über den Passwort-vergessen-Link weitergeleitet wird, um dort ein neues Passwort zu vergeben.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `newPassword` | Das neue Passwort, das für das Benutzerkonto gesetzt werden soll. |
| `newPasswordRepeat` | Wiederholung des neuen Passworts zur Vermeidung von Tippfehlern. |
| `passwordAuth` | Bisheriges Passwort des Benutzerkontos. Nicht erforderlich, wenn ein Opt-In-Token verwendet wird oder die Option `checkOldPassword` deaktiviert ist. |
| `email` | E-Mail-Adresse des Kontos. Nur erforderlich, wenn die Option `checkLoginID` aktiviert ist. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Weder ein Opt-In-Token noch eine eingeloggte Session ist vorhanden. |
| `missingPassword` | Parameter `newPassword` ist leer. |
| `passwordMismatch` | Parameter `newPassword`und `newPasswordRepeat`sind nicht identisch. |
| `missingPasswordAuth` | Parameter `passwordAuth` ist leer. Tritt nur ohne Opt-In-Token auf. |
| `failedPasswordAuth` | Parameter `passwordAuth` stimmt nicht mit dem bisherigen Passwort überein. |
| `passwordCheckFailed` | `newPassword` entspricht nicht den Passwortregeln. |
| `samePassword` | `newPassword` ist identisch mit dem bisherigen Passwort. |
Ist die Option `checkLoginID` aktiviert, gelten zusätzlich die Fehlercodes `missingEmail` (der Parameter `email` ist leer) und `emailMismatch` (die angegebene E-Mail-Adresse gehört nicht zum Konto).
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
* [\$wsAccount.isPasswordResetRequired](/frontend/referenz/module/wsAccount#%24wsaccount-ispasswordresetrequired)
**Beispiel** das zeigt, wie nach erfolgreichem Reset eine Bestätigung ausgegeben wird, bei einem gültigen Opt-In-Token das Formular zur Passwortvergabe erscheint und bei einem ungültigen Token ein Hinweis auf den abgelaufenen Link angezeigt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionResetPassword = $wsActions.create("ResetPassword") }}
{{ if $wsActions.current.success and $wsActions.current.name == "ResetPassword" }}
Das Passwort wurde geändert.
{{ elseif $wsOptIn.current }}
{{ if $wsOptIn.current.valid }}
{{ else }}
Der Link ist abgelaufen.
{{ /if }}
{{ /if }}
```
***
### CheckPasswordStrength
Mit dieser Aktion wird die Stärke eines eingegebenen Passworts in Echtzeit geprüft. Die Aktion wird per AJAX im Hintergrund ausgeführt und gibt ein JSON-Objekt mit dem Bewertungsergebnis zurück.
**Anwendungsbeispiel**\
Nutzbar auf Seiten mit Passwort-Eingabefeldern, beispielsweise auf der Registrierungsseite, um dem Kunden direktes Feedback zur Stärke ihres Passworts zu geben.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `password` | Das zu prüfende Passwort. |
| `email` | Optionale E-Mail-Adresse, die bei den Passwortprüfungen berücksichtigt wird. |
**Rückgabewerte**
| **Wert** | **Beschreibung** |
| - | - |
| `value` | Anzahl der erfüllten Prüfstufen. Der Wert `0` bedeutet, dass die Mindestanforderungen an das Passwort nicht erfüllt sind. |
| `max` | Anzahl aller Prüfstufen (Mindestanforderungen plus zusätzliche Stufen). |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
**Beispiel** das zeigt, wie die Passwortstärke bei Eingabe in Echtzeit geprüft und dem Benutzer visuell als schwach, mittel oder stark angezeigt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionCheckPasswordStrength = $wsActions.create("CheckPasswordStrength") }}
```
***
## Konto- & Kontaktdaten
### EmailUpdate
Mit dieser Aktion wird die hinterlegte E-Mail-Adresse eines Benutzerkontos geändert. Ist in der Konfiguration für die Änderung ein Double-Opt-In aktiviert, wird die neue Adresse erst nach Bestätigung des Opt-In-Links mit der Aktion `EmailUpdateOptIn` übernommen. Nach der Änderung werden die gespeicherten Auto-Login-Daten des Kontos verworfen.
**Anwendungsbeispiel**\
Nutzbar auf der Account-Verwaltungsseite, auf der eingeloggte Kunden ihre E-Mail-Adresse aktualisieren können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `email` | Neue E-Mail-Adresse, die für das Benutzerkonto hinterlegt werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingEmail` | Parameter `email` fehlt. |
| `emailCheckFailed` | Parameter `email` enthält keine gültige E-Mail-Adresse. |
| `accountAlreadyExists` | Es existiert bereits ein anderer Account mit dieser E-Mail-Adresse. |
| `updateFailed` | Die E-Mail-Adresse konnte nicht aktualisiert werden. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.email](/frontend/referenz/module/wsAccount#%24wsaccount-email)
**Beispiel** das ein Formular zur Eingabe einer neuen E-Mail-Adresse bereitstellt und nach erfolgreicher Ausführung eine Bestätigung ausgibt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionEmailUpdate = $wsActions.create("EmailUpdate") }}
{{ if $cActionEmailUpdate.success }}
E-Mail-Adresse erfolgreich aktualisiert.
{{ else }}
{{ /if }}
```
***
### EmailUpdateOptIn
Mit dieser Aktion wird die Änderung der E-Mail-Adresse per Opt-In-Token bestätigt. Der Token wird über einen Link in einer Bestätigungs-E-Mail an die neue E-Mail-Adresse übermittelt.
**Anwendungsbeispiel**\
Nutzbar auf der Bestätigungsseite, auf die der Kunde nach Klick auf den Opt-In-Link in der Bestätigungs-E-Mail weitergeleitet wird.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `actionNotAllowed` | Es wurde kein gültiger Opt-In-Token übergeben oder der Link ist abgelaufen. |
| `accountAlreadyExists` | Es existiert inzwischen bereits ein anderer Account mit der neuen E-Mail-Adresse. |
| `updateFailed` | Die E-Mail-Adresse konnte nicht aktualisiert werden. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
**Beispiel** das zeigt, wie bei einem gültigen Opt-In-Token ein Bestätigungsformular angezeigt wird, nach erfolgreicher Ausführung eine Erfolgsmeldung erscheint und bei einem abgelaufenen Token ein entsprechender Hinweis ausgegeben wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionEmailUpdateOptIn = $wsActions.create("EmailUpdateOptIn") }}
{{ if $wsActions.current.success and $wsActions.current.name == "EmailUpdateOptIn" }}
E-Mail-Adresse wurde erfolgreich geändert.
{{ elseif $wsOptIn.current.valid }}
{{ else }}
Der Token ist abgelaufen.
{{ /if }}
```
***
### accountDisplayNameUpdate
Mit dieser Aktion wird der Anzeigename eines Kundenkontos geändert.
**Anwendungsbeispiel**\
Nutzbar auf der Account-Verwaltungsseite, auf der eingeloggte Kunden ihren Anzeigenamen aktualisieren können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `displayName` | Der neue Anzeigename, der für das Benutzerkonto hinterlegt werden soll. |
**Fehlercodes**
| **Code** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `missingDisplayName` | Parameter `displayName` fehlt. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie die Aktion erstellt und in ein Formular eingebunden wird, über das der Kunde seinen Anzeigenamen aktualisieren kann.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionAccountDisplayNameUpdate = $wsActions.create("accountDisplayNameUpdate") }}
```
***
### AccountSetCustomerData
Mit dieser Aktion werden benutzerdefinierte Kundendaten für das eingeloggte Benutzerkonto gesetzt oder aktualisiert.
**Anwendungsbeispiel**\
Nutzbar auf der Account-Verwaltungsseite, auf der eingeloggte Kunden ihre persönlichen Daten wie beispielsweise ihr Geburtsdatum oder ihre Telefonnummer hinterlegen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `customerData.(fieldname)` | Die einzelnen Felder der Kundendaten. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `emptyCustomerData` | Es wurden keine Kundendatenfelder übergeben. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie die Aktion erstellt und in ein Formular eingebunden wird, über das der Kunde seine persönlichen Daten aktualisieren kann.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionAccountSetCustomerData = $wsActions.create("AccountSetCustomerData") }}
```
***
## Adressen
### AddressCreate
Mit dieser Aktion wird eine neue Adresse für den eingeloggten Benutzer erstellt.
**Anwendungsbeispiel**\
Nutzbar auf der Adressverwaltungsseite, auf der Kunden neue Liefer- oder Rechnungsadressen anlegen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `address.(fieldname)` | Die einzelnen Felder der Adresse, beispielsweise `address.firstName` oder `address.street`. |
| `type` | Art der Adresse: - `“bill”` - Rechnungsadresse - `“delivery”` - Lieferadresse Handelt es sich für das betreffende Kundenkonto um die erste Adresse seiner Art, wird sie automatisch als Hauptadresse für den jeweiligen Typ gesetzt. |
| `address.addressOwnerMemberId` | *(B2B)* ID des Mitarbeiters, dem die Adresse gehört. Wird das Feld nicht übergeben oder auf `0` gesetzt, ist die Adresse eine firmenweite Adresse, die jeder Mitarbeiter sehen und nutzen kann. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt und kein Opt-In-Token vorhanden. |
| `emptyAddress` | Es wurden keine Adressfelder übergeben. |
| `unknownField` | Ein übergebenes Adressfeld wird nicht unterstützt. |
| `invalidFieldType` | In einem Adressfeld wurde ein ungültiger Wert übergeben. |
| `missingAddressType` | Parameter `type` fehlt. |
| `invalidAddressType` | Parameter `type` enthält einen ungültigen Wert. |
| `maxBillAddressesReached` | Es können keine weiteren Rechnungsadressen angelegt werden. |
| `noPermission` | Der Benutzer hat keine Berechtigung, eine neue Adresse anzulegen (B2B). |
| `invalidMemberId` | Ungültige `address.addressOwnerMemberId` (B2B). |
| `subAccountDoesNotExist` | Das angegebene Mitarbeiterkonto wurde nicht gefunden (B2B). |
| `addressCheckFailed` | Fehler in den Adressdaten. Wird über Sub-Codes konkretisiert: - `minlen` = zu wenig Zeichen - `maxlen` = zu viele Zeichen - `numeric` = ungültige Zeichen - `country` = Land nicht konfiguriert - `zip` = Postleitzahl fehlerhaft |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#%24wsaccount-addresses)
**Beispiel** das zeigt, wie eine neue Adresse über ein Formular mit einzelnen Adressfeldern angelegt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionAddressCreate = $wsActions.create("AddressCreate") }}
```
**Beispiel (B2B)** das zeigt, wie eine Lieferadresse angelegt wird, die nur einem bestimmten Mitarbeiter gehört.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionAddressCreate = $wsActions.create("AddressCreate") }}
```
***
### AddressUpdate
Mit dieser Aktion wird eine bestehende Adresse des eingeloggten Benutzers bearbeitet.
**Anwendungsbeispiel**\
Nutzbar auf der Adressverwaltungsseite, wenn ein Kunde eine seiner gespeicherten Adressen aktualisieren möchte.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `addressId` | Die ID der Adresse, die bearbeitet werden soll. |
| `address.(fieldname)` | Die einzelnen Felder der Adresse, die aktualisiert werden sollen. |
| `type` | Art der Adresse: - `“bill”` - Rechnungsadresse - `“delivery”` - Lieferadresse |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt und es ist kein Opt-In-Token vorhanden. |
| `emptyAddress` | Es wurden keine Adressfelder übergeben. |
| `invalidAddressId` | Ungültige `addressId` - die Adresse existiert nicht oder gehört nicht zu diesem Benutzerkonto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#%24wsaccount-addresses)
* [\$wsAccount.loadAddress](/frontend/referenz/module/wsAccount#%24wsaccount-loadaddress)
**Beispiel** das zeigt, wie eine bestehende Adresse anhand ihrer ID bearbeitet wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionAddressUpdate = $wsActions.create("AddressUpdate") }}
```
***
### AddressDelete
Mit dieser Aktion wird eine Adresse des eingeloggten Benutzers gelöscht.
**Anwendungsbeispiel**\
Nutzbar auf der Adressverwaltungsseite, wenn ein Kunde eine nicht mehr benötigte Adresse entfernen möchte.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `addressId` | Die ID der Adresse, die gelöscht werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt und es ist kein Opt-In-Token vorhanden. |
| `invalidAddressId` | Ungültige `addressId` - die Adresse existiert nicht oder gehört nicht zu diesem Benutzerkonto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#%24wsaccount-addresses)
**Beispiel** das zeigt, wie eine Adresse über ihre ID gelöscht wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionAddressDelete = $wsActions.create("AddressDelete") }}
```
***
### SetMainAddress
Mit dieser Aktion wird eine gespeicherte Adresse als Hauptadresse festgelegt. Die Hauptadresse wird im Checkout automatisch vorausgewählt.
**Anwendungsbeispiel**\
Nutzbar auf der Adressverwaltungsseite, damit Kunden ihre bevorzugte Adresse als Standard für zukünftige Bestellungen hinterlegen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `addressId` | Die ID der Adresse, die als Hauptadresse gesetzt werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `missingAddressId` | Parameter `addressId` fehlt. |
| `invalidAddressId` | Ungültige `addressId` - die Adresse existiert nicht oder gehört zu einem anderen Konto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#%24wsaccount-addresses)
**Beispiel** das zeigt, wie eine Adresse per Button als Hauptadresse gesetzt wird, sofern sie es nicht bereits ist.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionSetMainAddress = $wsActions.create("SetMainAddress") }}
{{ foreach $cAddress in $wsAccount.addresses }}
{{ if $cAddress.id != $wsAccount.mainAddress.id }}
{{ /if }}
{{ /foreach }}
```
***
### SetDefaultBillAddress
Mit dieser Aktion wird eine gespeicherte Adresse als Standard-Rechnungsadresse festgelegt. Die Standard-Rechnungsadresse wird im Checkout automatisch als Rechnungsadresse vorausgewählt.
**Anwendungsbeispiel**\
Nutzbar auf der Adressverwaltungsseite, damit Kunden eine bevorzugte Rechnungsadresse als Standard für zukünftige Bestellungen hinterlegen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `addressId` | Die ID der Adresse, die als Standard-Rechnungsadresse gesetzt werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `missingAddressId` | Parameter `addressId` fehlt. |
| `invalidAddressId` | Ungültige `addressId` - die Adresse existiert nicht oder gehört zu einem anderen Konto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#%24wsaccount-addresses)
* [\$wsAccount.defaultBillAddress](/frontend/referenz/module/wsAccount#%24wsaccount-defaultbilladdress)
**Beispiel** das zeigt, wie eine Adresse per Button als Standard-Rechnungsadresse gesetzt wird, sofern sie es nicht bereits ist.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionSetDefaultBillAddress = $wsActions.create("SetDefaultBillAddress") }}
```
***
### SetDefaultDeliveryAddress
Mit dieser Aktion wird eine gespeicherte Adresse als Standard-Lieferadresse festgelegt. Die Standard-Lieferadresse wird im Checkout automatisch als Lieferadresse vorausgewählt.
**Anwendungsbeispiel**\
Nutzbar auf der Adressverwaltungsseite, damit Kunden eine bevorzugte Lieferadresse als Standard für zukünftige Bestellungen hinterlegen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `addressId` | Die ID der Adresse, die als Standard-Lieferadresse gesetzt werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `missingAddressId` | Parameter `addressId` fehlt. |
| `invalidAddressId` | Ungültige `addressId` - die Adresse existiert nicht oder gehört zu einem anderen Konto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#%24wsaccount-addresses)
* [\$wsAccount.defaultDeliveryAddress](/frontend/referenz/module/wsAccount#\$wsaccount-defaultdeliveryaddress)
**Beispiel** das zeigt, wie eine Adresse per Button als Standard-Lieferadresse gesetzt wird, sofern sie es nicht bereits ist.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionSetDefaultDeliveryAddress = $wsActions.create("SetDefaultDeliveryAddress") }}
```
***
### RemoveDefaultBillAddress
Mit dieser Aktion wird die gesetzte Standard-Rechnungsadresse des eingeloggten Benutzers entfernt.
**Anwendungsbeispiel**\
Nutzbar auf der Adressverwaltungsseite, wenn ein Kunde die Standard-Rechnungsadresse zurücksetzen möchte, sodass im Checkout keine Adresse mehr vorausgewählt ist.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#%24wsaccount-addresses)
* [\$wsAccount.defaultBillAddress](/frontend/referenz/module/wsAccount#%24wsaccount-defaultbilladdress)
**Beispiel** das zeigt, wie die Standard-Rechnungsadresse über einen Button entfernt wird, sofern eine gesetzt ist.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionRemoveDefaultBillAddress = $wsActions.create("RemoveDefaultBillAddress") }}
```
***
### RemoveDefaultDeliveryAddress
Mit dieser Aktion wird die gesetzte Standard-Lieferadresse des eingeloggten Benutzers entfernt.
**Anwendungsbeispiel**\
Nutzbar auf der Adressverwaltungsseite, wenn ein Kunde die Standard-Lieferadresse zurücksetzen möchte, sodass im Checkout keine Adresse mehr vorausgewählt ist.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#%24wsaccount-addresses)
* [\$wsAccount.defaultDeliveryAddress](/frontend/referenz/module/wsAccount#\$wsaccount-defaultdeliveryaddress)
**Beispiel** das zeigt, wie die Standard-Lieferadresse über einen Button entfernt wird, sofern eine gesetzt ist.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionRemoveDefaultDeliveryAddress = $wsActions.create("RemoveDefaultDeliveryAddress") }}
```
***
## Kreditkarten
### CreditCardDelete
Mit dieser Aktion wird eine gespeicherte Kreditkarte aus dem Kundenkonto gelöscht.
**Anwendungsbeispiel**\
Nutzbar auf der Kreditkartenverwaltungsseite, auf der eingeloggte Kunden ihre gespeicherten Kreditkarten einsehen und entfernen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `pseudoCCId` | Die ID der Kreditkarte, die gelöscht werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `invalidPseudoCCId` | Ungültige `pseudoCCId` - die Kreditkarte existiert nicht oder gehört nicht zu diesem Benutzerkonto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.pseudoCreditCards](/frontend/referenz/module/wsAccount#%24wsaccount-pseudocreditcards)
**Beispiel** das zeigt, wie alle gespeicherten Kreditkarten aufgelistet werden und jede einzelne über einen Button gelöscht werden kann.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cCreditCards = $wsAccount.pseudoCreditCards }}
{{ foreach $cCreditCard in $wsAccount.pseudoCreditCards }}
{{ var $cActionCreditCardDelete = $wsActions.create("CreditCardDelete") }}
{{ /foreach }}
```
***
## Gast → Konto
### GuestRegister
Mit dieser Aktion wird aus einem Gast-Checkout ein vollwertiges Kundenkonto erstellt. Der Gast gibt dabei ein Passwort an, die E-Mail-Adresse wird automatisch aus den Checkout-Daten übernommen.
**Anwendungsbeispiel**\
Nutzbar auf der Bestellbestätigungsseite nach einem Gast-Checkout, auf der nicht eingeloggte Kunden die Möglichkeit erhalten, sich direkt ein Konto anzulegen.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `guestMail` | E-Mail-Adresse des Gast-Kontos, wird automatisch aus den Checkout-Daten übernommen. |
| `password` | Neues Passwort für das Kundenkonto. |
| `passwordRepeat` | Wiederholung des Passworts. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `nonGuestAccount` | Der Benutzer ist bereits in einem Kundenkonto eingeloggt. |
| `missingEmail` | Parameter `guestMail` ist leer. |
| `missingPassword` | Parameter `password` ist leer. |
| `passwordMismatch` | Parameter `password` und `passwordRepeat` sind nicht identisch. |
| `passwordCheckFailed` | Passwort erfüllt nicht die erforderlichen Richtlinien. Wird über Sub-Codes konkretisiert: - `minlen` = zu wenig Zeichen - `maxlen` = zu viele Zeichen |
| `duplicateEmail` | Für die E-Mail-Adresse existiert bereits ein Kundenkonto. |
| `createError` | Das Kundenkonto konnte nicht angelegt werden. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
* [\$wsAccount.email](/frontend/referenz/module/wsAccount#%24wsaccount-email)
**Beispiel** das zeigt, wie nicht eingeloggten Kunden nach einem Gast-Checkout die Möglichkeit geboten wird, ein Kundenkonto anzulegen, inklusive Erfolgsausgabe.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if not $wsAccount.isLoggedIn }}
{{ var $cGuestRegister = $wsActions.create("GuestRegister") }}
{{ if $cGuestRegister.success }}
Es wurde ein Konto angelegt.
{{ /if }}
{{ if not $cGuestRegister.success }}
{{ /if }}
{{ /if }}
```
***
### SaveGuestDataToUser
Mit dieser Aktion wird aus den Daten eines Gast-Checkouts ein vollwertiges Kundenkonto erstellt. Der Gast gibt dabei ein Passwort an und erhält damit Zugang zu einem dauerhaften Konto.
**Anwendungsbeispiel**\
Nutzbar auf der Bestellbestätigungsseite nach einem Gast-Checkout, um dem Kunden die Möglichkeit zu geben, sich direkt ein Konto anzulegen, ohne erneut alle Daten eingeben zu müssen.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `id` | E-Mail-Adress des Gast-Kontos. |
| `password` | Neues Passwort für das Kundenkonto. |
| `passwordRepeat` | Wiederholung des Passworts. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `nonGuestAccount` | Der Benutzer ist bereits in einem Kundenkonto eingeloggt. |
| `missingId` | Parameter `id` fehlt. |
| `missingPassword` | Parameter `password` fehlt. |
| `passwordMismatch` | Parameter `password` und `passwordRepeat` sind nicht identisch. |
| `passwordCheckFailed` | Passwortregel-Prüfung ist fehlgeschlagen. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#%24wsaccount-addresses)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie ein Gast-Kunde nach dem Checkout ein dauerhaftes Konto anlegen kann, indem er nur ein Passwort vergeben muss.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionSaveGuestDataToUser = $wsActions.create("SaveGuestDataToUser") }}
```
***
## B2B – Mitarbeiterkonten
Alle Aktionen in diesem Abschnitt setzen Admin-Rechte voraus und sind nur für Firmenkonten im B2B-Bereich zur verfügbar. Eine Einführung in das Zusammenspiel von Mitarbeiterkonten und Berechtigungsgruppen finden Sie im Abschnitt [Grundkonzept](#grundkonzept).
### SubAccountCreate
Mit dieser Aktion wird ein neues Mitarbeiterkonto angelegt. An die angegebene E-Mail-Adresse wird automatisch eine [E-Mail](https://dokumentation.websale.de/konfiguration/b2b-business-to-business-b2b#b2b-userinvitation-benutzereinladung) mit einem Link zum Setzen des Passworts gesendet. Für diese Aktion sind Admin-Rechte erforderlich.
**Anwendungsbeispiel**\
Nutzbar auf der Account-Verwaltungsseite, auf der Administratoren neue Mitarbeiterkonten anlegen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `email` | E-Mail-Adresse des neuen Mitarbeiterkontos.
An diese Adresse wird der Link zum Setzen des Passworts gesendet. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `disabled` | Die Verwaltung von Mitarbeiterkonten ist in diesem Shop nicht aktiviert. |
| `notLoggedIn` | Der Benutzer ist nicht als Administrator des Firmenkontos eingeloggt. |
| `accountNotVerified` | Das Firmenkonto ist noch nicht verifiziert. |
| `missingId` | Parameter `email` ist leer. |
| `emailCheckFailed` | Parameter `email` enthält eine ungültige E-Mail-Adresse. |
| `accountAlreadyExists` | Es existiert bereits ein Account mit der angegebenen E-Mail-Adresse. |
| `mailSendFailed` | Die Einladungs-E-Mail konnte nicht versendet werden. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie die Aktion erstellt und in ein Formular eingebunden wird, über das ein neues Mitarbeiterkonto angelegt werden kann.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionSubAccountCreate = $wsActions.create("SubAccountCreate") }}
```
***
### UpdateSubAccount
Mit dieser Aktion werden die Einstellungen des bestehenden Mitarbeiterkontos aktualisiert. Eine Deaktivierung des eigenen Kontos oder das Entziehen der Admin-Rechte ist nicht möglich. Für diese Aktion sind Admin-Rechte erforderlich.
**Anwendungsbeispiel**\
Nutzbar auf der Mitarbeiterverwaltungsseite, auf der Administratoren Rollen und weitere Einstellungen von Mitarbeiterkonten anpassen können.
**Parameter**
| Name | Beschreibung |
| - | - |
| `memberId` | Die ID des Mitarbeiterkontos, das aktualisiert werden soll. |
| `displayName` | Anzeigename des Mitarbeiterkontos. |
| `active` | Gibt an, ob sich das Mitarbeiterkonto anmelden darf (`true` / `false`).
Das eigene Konto kann nicht deaktiviert werden. |
| `admin` | Gibt an, ob das Konto Admin-Rechte besitzt (`true` / `false`).
Dem eigenen Konto können keine Admin-Rechte entzogen werden. |
| `privilegeGroupId` | ID der Berechtigungsgruppe, die dem Mitarbeiterkonto zugewiesen wird. |
| `defaultAddressVisibility` | Legt fest, welche Sichtbarkeit beim Anlegen neuer Adressen standardmäßig vorausgewählt ist.
Mögliche Werte:
- `private` (nur für dieses Konto sichtbar)
- `shared` (firmenweit freigegeben) |
| `allowedSubshops` | Legt fest, auf welche Subshops das Mitarbeiterkonto Zugriff hat.
Die [Subshop-IDs](https://dokumentation.websale.de/frontend/referenz/module/wssubshop#\$wssubshop-subshops) werden als Schlüssel eines JSON-Objekts übergeben, beispielsweise `{"shop1": true, "shop2": true}.` |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `disabled` | Die Verwaltung von Mitarbeiterkonten ist in diesem Shop nicht aktiviert. |
| `notLoggedIn` | Der Benutzer ist nicht als Administrator des Firmenkontos eingeloggt. |
| `invalidMemberId` | Parameter `memberId` fehlt oder ist ungültig. |
| `subAccountDoesNotExist` | Das Mitarbeiterkonto existiert nicht oder gehört nicht zu diesem Account. |
| `selfDeactivationNotAllowed` | Die Parameter `active` oder `admin` wurden für das eigene Konto übergeben. Das eigene Konto kann weder deaktiviert noch seiner Admin-Rechte beraubt werden. |
| `updateFailed` | Die Änderungen konnten nicht gespeichert werden. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](https://dokumentation.websale.de/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](https://dokumentation.websale.de/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
* [\$wsSubshop.subshops](https://dokumentation.websale.de/frontend/referenz/module/wssubshop#\$wssubshop-subshops)
**Beispiel** das zeigt, wie die Einstellungen eines Mitarbeiterkontos über ein Formular aktualisiert werden.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionUpdateSubAccount = $wsActions.create("UpdateSubAccount") }}
```
***
### SubAccountDelete
Mit dieser Aktion wird ein bestehendes Mitarbeiterkonto gelöscht. Das eigene Konto sowie Konten mit Admin-Rechten können nicht gelöscht werden. Für diese Aktion sind Admin-Rechte erforderlich.
**Anwendungsbeispiel**\
Nutzbar auf der Mitarbeiterverwaltungsseite, auf der Administratoren nicht mehr benötigte Mitarbeiterkonten entfernen können.
**Parameter**
| Name | Beschreibung |
| - | - |
| `memberId` | Die ID des Mitarbeiterkontos, das gelöscht werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `disabled` | Die Verwaltung von Mitarbeiterkonten ist in diesem Shop nicht aktiviert. |
| `notLoggedIn` | Der Benutzer ist nicht als Administrator des Firmenkontos eingeloggt. |
| `selfDeletionNotAllowed` | Das eigene Konto kann nicht gelöscht werden. |
| `invalidMemberId` | Parameter `memberId` fehlt oder ist ungültig. |
| `subAccountDoesNotExist` | Das Mitarbeiterkonto existiert nicht oder gehört nicht zu diesem Account. |
| `noPermission` | Konten mit Admin-Rechten können nicht gelöscht werden. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](https://dokumentation.websale.de/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](https://dokumentation.websale.de/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie ein Mitarbeiterkonto über seine ID gelöscht wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionSubAccountDelete = $wsActions.create("SubAccountDelete") }}
```
***
### AcceptInvitation
Mit dieser Aktion nimmt ein B2B-Firmenkunde eine Einladung per Double-Opt-In-Verfahren an. Der Token ist in einem Link enthalten, den der Kunde per E-Mail erhält. Nach erfolgreicher Verifizierung hat das Konto vollen Zugriff auf den Shop.
**Anwendungsbeispiel**\
Nutzbar auf der Bestätigungsseite, auf die der eingeladene Kunde nach Klick auf den Einladungslink in der E-Mail weitergeleitet wird.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `unauthorized` | Es wurde kein gültiger Opt-In-Token übergeben. |
| `invalidAccountId` | Der Double-Opt-In-Token konnte keinem Kundenkonto zugeordnet werden. |
| `actionNotAllowed` | Der Double-Opt-In-Token ist ungültig oder passt nicht zum Konto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.isAccountVerified](/frontend/referenz/module/wsAccount#%24wsaccount-isaccountverified)
**Beispiel** das zeigt, wie nach erfolgreicher Annahme der Einladung eine Bestätigungsmeldung angezeigt wird.
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current.name == "AcceptInvitation" and $wsActions.current.success }}
Einladung wurde angenommen.
{{ /if }}
```
***
## B2B – Berechtigungsgruppen
Alle Aktionen in diesem Abschnitt setzen Admin-Rechte voraus und sind nur für Firmenkonten im B2B-Bereich verfügbar. Informationen zum Zusammenspiel mit Mitarbeiterkonten finden Sie im Abschnitt [Grundkonzept](#grundkonzept).
### CreatePrivilegeGroup
Mit dieser Aktion wird eine neue Berechtigungsgruppe erstellt. Für diese Aktion sind Admin-Rechte erforderlich.
**Anwendungsbeispiel**\
Nutzbar auf der Berechtigungsverwaltungsseite, auf der Administratoren neue Gruppen mit definierten Rechten für Mitarbeiterkonten erstellen können.
**Parameter**
| Name | Beschreibung |
| - | - |
| `name` | Name der neuen Berechtigungsgruppe. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `disabled` | Die Verwaltung von Mitarbeiterkonten ist in diesem Shop nicht aktiviert. |
| `notLoggedIn` | Der Benutzer ist nicht als Administrator des Firmenkontos eingeloggt. |
| `invalidGroupName` | Parameter `name` fehlt oder ist leer. |
| `creationFailed` | Die Berechtigungsgruppe konnte nicht angelegt werden. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](https://dokumentation.websale.de/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](https://dokumentation.websale.de/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie eine neue Berechtigungsgruppe über ein Formular angelegt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionCreatePrivilegeGroup = $wsActions.create("CreatePrivilegeGroup") }}
```
***
### UpdatePrivileges
Mit dieser Aktion wird eine Berechtigungsgruppe aktualisiert. Für diese Aktion sind Admin-Rechte erforderlich.
**Anwendungsbeispiel**\
Nutzbar auf der Berechtigungsverwaltungsseite, auf der Administratoren Rechte und Einschränkungen für Berechtigungsgruppen definieren können.
**Parameter**
| Name | Beschreibung |
| - | - |
| `privilegeId` | Die ID der Berechtigungsgruppe, die aktualisiert werden soll. |
| `createMissing` | Gibt an, ob die Gruppe automatisch erstellt werden soll, falls sie nicht existiert.
Mögliche Werte:
- `yes` |
| `type` | Art der Berechtigungsgruppe:
- `global` (shopweit)
- `account` (kontobezogen) |
| `privileges` | JSON-Objekt mit den Berechtigungsfeldern.
Mögliche Felder:
- `allowedPaymentMethods` (JSON-Objekt mit erlaubten Zahlungsarten: Zahlarten-ID als Schlüssel, `"1"` als Wert schaltet die Zahlart frei, alle anderen Werte werden ignoriert)
- `paymentLimitPerOrder` (maximaler Bestellwert pro Bestellung)
- `paymentLimit` (globale Budgetgrenze über alle Bestellungen seit Limitsetzung)
- `blockedTemplates` (gesperrte Templates / Seiten der Gruppe)
- `blockedUrls` (gesperrte URLs der Gruppe)
- `editableFields` (bearbeitbare Felder der Gruppe)
- `groupName` (nur relevant bei `type = global`) |
Die beiden Budgetgrenzen wirken zusammen: `paymentLimitPerOrder` begrenzt jede einzelne Bestellung, `paymentLimit` die kumulierte Ausgabensumme. Beide Werte werden im Frontend schreibgeschützt direkt am Account gelesen, über [\$wsAccount.paymentLimit](/frontend/referenz/module/wsAccount) bzw. `$wsAccount.paymentLimitPerOrder`.
Über `allowedPaymentMethods` können nur Zahlarten freigeschaltet werden, die auch für das Firmenkonto selbst verfügbar sind: Zahlarten, die für das Konto gesperrt sind (`blockedPaymentMethods`) oder in der Shop-Konfiguration mit `availableByDefault: false` angelegt und nicht gezielt für das Konto freigeschaltet wurden (`enabledPaymentMethods`), können keiner Berechtigungsgruppe zugewiesen werden (siehe [Konfiguration Zahlungsmethoden](/konfiguration/payment-zahlungsmethoden)).
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `disabled` | Die Verwaltung von Rechtegruppen ist für das Firmenkonto nicht aktiviert. |
| `notLoggedIn` | Der Benutzer ist nicht als Administrator des Firmenkontos eingeloggt. |
| `invalidPrivilegeId` | Parameter `privilegeId` fehlt oder ist ungültig und `createMissing` ist nicht gesetzt. |
| `invalidPrivilegeType` | Parameter `type` enthält einen ungültigen Wert. |
| `missingPrivileges` | Parameter `privileges` fehlt oder ist leer. |
| `paymentMethodNotAllowedByAccount` | Eine Zahlart in `allowedPaymentMethods` ist für das Firmenkonto selbst nicht verfügbar (gesperrt oder nicht freigeschaltet). |
| `updateFailed` | Die Berechtigungsgruppe konnte nicht gespeichert werden. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](https://dokumentation.websale.de/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](https://dokumentation.websale.de/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
* [\$wsAccount.paymentLimit](/frontend/referenz/module/wsAccount)
**Beispiel** das zeigt, wie die Berechtigungen einer Gruppe inklusive globaler und bestellbezogener Budgetgrenze aktualisiert werden.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionUpdatePrivileges = $wsActions.create("UpdatePrivileges") }}
```
***
### DeletePrivilegeGroup
Mit dieser Aktion wird eine bestehende Berechtigungsgruppe gelöscht. Eine Gruppe kann jedoch nicht gelöscht werden, solange ihr noch Mitarbeiterkonten zugewiesen sind. Für diese Aktion sind Admin-Rechte erforderlich.
**Anwendungsbeispiel**\
Nutzbar auf der Berechtigungsverwaltungsseite, wenn eine nicht mehr benötigte Berechtigungsgruppe entfernt werden soll.
**Parameter**
| Name | Beschreibung |
| - | - |
| `id` | Die ID der Berechtigungsgruppe, die gelöscht werden soll. |
| `unlinkMembers` | Gibt an, ob zugewiesene Mitarbeiterkonten vor dem Löschen aus der Gruppe entfernt werden (`true` / `false`). Ohne diese Angabe wird die Gruppe nicht gelöscht, solange ihr Mitarbeiterkonten zugewiesen sind. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `disabled` | Die Verwaltung von Mitarbeiterkonten ist in diesem Shop nicht aktiviert. |
| `notLoggedIn` | Der Benutzer ist nicht als Administrator des Firmenkontos eingeloggt. |
| `invalidGroupId` | Parameter `id` fehlt oder ist ungültig, die Berechtigungsgruppe existiert nicht oder gehört nicht zu diesem Account. |
| `groupInUse` | Die Berechtigungsgruppe kann nicht gelöscht werden, da ihr noch Mitarbeiterkonten zugewiesen sind. |
| `unlinkMemberFailed` | Beim Entfernen der Mitarbeiterkonten aus der Berechtigungsgruppe ist ein Fehler aufgetreten. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](https://dokumentation.websale.de/frontend/referenz/module/wsAccount)
* [\$wsAccount.isLoggedIn](https://dokumentation.websale.de/frontend/referenz/module/wsAccount#%24wsaccount-isloggedin)
**Beispiel** das zeigt, wie eine Berechtigungsgruppe über ihre ID gelöscht wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionDeletePrivilegeGroup = $wsActions.create("DeletePrivilegeGroup") }}
```
# Basket
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/basket
Warenkorb-Aktionen im Überblick: BasketItemAdd, BasketItemUpdate, BasketItemDelete sowie VoucherAdd und VoucherDelete zum Verwalten des Warenkorbs.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich Warenkorb beschrieben. Mit diesen Aktionen können Produkte hinzugefügt, aktualisiert und entfernt sowie Gutscheine verwaltet werden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `BasketItemAdd` | Legt ein Produkt in den Warenkorb. |
| `BasketItemUpdate` | Aktualisiert die Menge eines Produkts im Warenkorb. |
| `BasketItemDelete` | Entfernt ein Produkt aus dem Warenkorb. |
| `VoucherAdd` | Löst einen Gutscheincode im Warenkorb ein. |
| `VoucherDelete` | Entfernt einen eingelösten Gutschein aus dem Warenkorb. |
***
## Aktionen
### BasketItemAdd
Mit dieser Aktion wird ein Produkt in den Warenkorb gelegt.
**Anwendungsbeispiel**\
Nutzbar auf Produktdetail-, Kategorie- oder Merklisten-Seiten, auf denen Kunden Produkte direkt in den Warenkorb legen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `productId` | Die ID des Produkts, das in den Warenkorb gelegt werden soll. |
| `quantity` | Die gewünschte Menge des Produkts. |
| `multiProducts..quantity` | Ermöglicht das gleichzeitige Hinzufügen mehrerer Produkte mit jeweiliger Menge. Ersetzt `productId` und `quantity`. Eine Variante wird über `multiProducts...quantity` übergeben. Ist eines der Produkte ungültig, legt der Shop keines davon in den Warenkorb. |
| `insert` | Das [Werbemittelkennzeichen](/frontend/funktionsubersicht/werbemittelkennzeichnung) der Position. Gilt auch beim Hinzufügen eines einzelnen Produkts. Beim Hinzufügen mehrerer Produkte lautet der Parameter `multiProducts..insert`. |
| `freeFieldscategoryPath` | Optionales Freifeld zur Übergabe des Kategoriepfads, beispielsweise für Tracking-Zwecke. |
Über `multiProducts` werden beispielsweise beim Bestellschein der Direktbestellung alle erfassten Positionen in den Warenkorb übernommen, siehe [Positionen in den Warenkorb übernehmen](/frontend/referenz/module/wsdirectorder#positionen-in-den-warenkorb-übernehmen).
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingProductId` | Parameter `productId` fehlt. |
| `invalidProductId` | Das Produkt existiert nicht oder ist nicht verfügbar. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsBasket](/frontend/referenz/module/wsbasket)
* [\$wsBasket.items](/frontend/referenz/module/wsbasket#\$wsbasket-items)
* [\$wsBasket.lastBasketAction](/frontend/referenz/module/wsbasket#\$wsbasket-lastbasketaction)
* [\$wsBasket.lastUpdatedItem](/frontend/referenz/module/wsbasket#\$wsbasket-lastupdateditem)
**Beispiel** das zeigt, wie ein Produkt mit Mengenauswahl in den Warenkorb gelegt wird und nach erfolgreicher Ausführung eine Bestätigungsmeldung erscheint.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsActions.current.success and $wsActions.current.name == "BasketItemAdd" }}
Produkt zum Warenkorb hinzugefügt.
{{ /if }}
{{ var $myActionBasketItemAdd = $wsActions.create("BasketItemAdd") }}
```
***
### BasketItemUpdate
Mit dieser Aktion wird die Menge eines im Warenkorb enthaltenen Produkts aktualisiert.
**Anwendungsbeispiel**\
Nutzbar auf der Warenkorbseite oder im Warenkorb-Offcanvas, wenn Kunden die Menge eines bereits hinzugefügten Produkts anpassen möchten.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `basketItemId` | Die ID des Warenkorb-Eintrags, dessen Menge aktualisiert werden soll. |
| `quantity` | Die neue Menge des Produkts. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingBasketItemId` | Parameter `basketItemId` fehlt. |
| `invalidBasketItemId` | Der Warenkorb-Eintrag existiert nicht oder gehört nicht zu diesem Warenkorb. |
| `missingQuantity` | Parameter `quantity` fehlt. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsBasket](/frontend/referenz/module/wsbasket)
* [\$wsBasket.items](/frontend/referenz/module/wsbasket#\$wsbasket-items)
* [\$wsBasket.lastBasketAction](/frontend/referenz/module/wsbasket#\$wsbasket-lastbasketaction)
* [\$wsBasket.lastUpdatedItem](/frontend/referenz/module/wsbasket#\$wsbasket-lastupdateditem)
**Beispiel** das zeigt, wie die Menge eines Warenkorb-Eintrags über ein Formular aktualisiert wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionBasketItemUpdate = $wsActions.create("BasketItemUpdate", tag = $myProduct.id) }}
```
***
### BasketItemDelete
Mit dieser Aktion wird ein Produkt aus dem Warenkorb entfernt.
**Anwendungsbeispiel**\
Nutzbar auf der Warenkorbseite oder im Warenkorb-Offcanvas, wenn Kunden ein Produkt vollständig aus dem Warenkorb entfernen möchten.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `basketItemId` | Die ID des Warenkorb-Eintrags, der entfernt werden soll. |
| `productId` | Die ID des Produkts, das entfernt werden soll. |
| `quantity` | Die aktuelle Menge des Produkts. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingBasketItemId` | Parameter `basketItemId` fehlt. |
| `invalidBasketItemId` | Der Warenkorb-Eintrag existiert nicht oder gehört nicht zu diesem Warenkorb. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsBasket](/frontend/referenz/module/wsbasket)
* [\$wsBasket.items](/frontend/referenz/module/wsbasket#\$wsbasket-items)
* [\$wsBasket.lastBasketAction](/frontend/referenz/module/wsbasket#\$wsbasket-lastbasketaction)
* [\$wsBasket.lastUpdatedItem](/frontend/referenz/module/wsbasket#\$wsbasket-lastupdateditem)
**Beispiel** das zeigt, wie ein Produkt über einen Button aus dem Warenkorb entfernt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionBasketItemDelete = $wsActions.create("BasketItemDelete", tag = $myProduct.id) }}
```
# Checkout
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/checkout
Checkout-Aktionen für den Bestellablauf: Rechnungs- und Lieferadressen auswählen, zwischenspeichern und in den Bestellprozess übernehmen.
In diesem Abschnitt werden die verfügbaren Aktionen im Checkout beschrieben. Mit diesen Aktionen können beispielsweise Rechnungs- und Lieferadressen ausgewählt, zwischengespeichert und übernommen werden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `CheckoutAccountTypeSelect` | Legt den Kontotyp für den aktuellen Bestellvorgang fest. |
| `CheckoutBillAddressSelect` | Setzt eine gespeicherte Adresse als aktive Rechnungsadresse. |
| `CheckoutShippingAddressSelect` | Setzt eine gespeicherte Adresse als aktive Lieferadresse. |
| `CheckoutSetDraftAddress` | Speichert eine Adresse temporär als Entwurf (ohne Validierung). |
| `CheckoutCommitDraftAddress` | Übernimmt einen Adressentwurf als verbindliche Checkout-Adresse (mit Validierung). |
| `CheckoutUseSameShippingAddress` | Setzt die Lieferadresse gleich der Rechnungsadresse. |
| `CheckoutUseDifferentShippingAddress` | Aktiviert eine abweichende Lieferadresse. |
| `CheckoutSetGuestEmail` | Setzt die E-Mail-Adresse für eine Gastbestellung. |
| `CheckoutPaymentUpdate` | Setzt die Zahlungsart für den aktuellen Bestellvorgang. |
| `CheckoutShippingMethodUpdate` | Setzt die Versandart für den aktuellen Bestellvorgang. |
| `CheckoutConfirm` | Schickt die Bestellung verbindlich ab. |
| `RefreshPaymentStatus` | Aktualisiert den Status einer laufenden Zahlung und gibt ihn zurück. |
| `CheckoutSetFreeFields` | Setzt die freien Checkout-Felder, beispielsweise die AGB-Zustimmung. |
| `CheckoutSetPaymentFields` | Speichert die Zusatzfelder der gewählten Zahlungsart, beispielsweise das Geburtsdatum für den Kauf auf Rechnung. |
| `CheckoutSetCustomerData` | Setzt Kundendaten im Checkout. |
| `CheckoutPseudoCCSelect` | Wählt eine gespeicherte Pseudo-Kreditkarte aus. |
| `CheckoutNewsletterSubscribe` | Meldet den Kunden während des Checkouts zum Newsletter an. |
| `CheckoutSetVerificationStatus` | Setzt den Verifizierungsstatus der Bestellung. (**Doku folgt**) |
| `CheckoutStoreIdSelect` | Setzt einen Markt als Abholort für den aktuellen Bestellvorgang. |
***
## Aktionen
### CheckoutBillAddressSelect
Mit dieser Aktion wählt der Kunde eine seiner bereits gespeicherten Adressen als Rechnungsadresse für den aktuellen Bestellvorgang aus. Die Auswahl wird sofort übernommen, es ist keine weitere Bestätigung nötig.
**Anwendungsbeispiel**
Nutzbar, um beispielsweise eingeloggten Kunden im Checkout ein Dropdown mit ihren gespeicherten Adressen anzuzeigen, sodass sie eine Rechnungsadresse mit einem Klick auswählen können, ohne erneute Eingabe.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `addressId` | Die ID der Adresse, die als Rechnungsadresse gesetzt werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingAddressId` | Parameter `addressId` fehlt. |
| `invalidAddressId` | Die angegebene Adresse existiert nicht oder gehört nicht zu diesem Kundenkonto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.selectedBillAddress](/frontend/referenz/module/wscheckout#\$wscheckout-selectedbilladdress)
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#\$wsaccount-addresses)
**Beispiel** das zeigt, wie eingeloggten Kunden ein Dropdown mit ihren gespeicherten Adressen angezeigt wird, über das sie eine Rechnungsadresse auswählen können.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myCheckoutBillAddressSelect = $wsActions.create("CheckoutBillAddressSelect") }}
```
***
### CheckoutShippingAddressSelect
Mit dieser Aktion wählt der Kunde eine seiner bereits gespeicherten Adressen als Lieferadresse für den aktuellen Bestellvorgang aus. Die Aktion ist nur relevant, wenn der Kunde eine abweichende Lieferadresse angeben möchte.
**Anwendungsbeispiel**
Nutzbar, wenn ein Kunde eine Bestellung an eine andere Adresse schicken möchte.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `addressId` | Die ID der Adresse, die als Lieferadresse gesetzt werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingAddressId` | Parameter `addressId` fehlt. |
| `invalidAddressId` | Die angegebene Adresse existiert nicht oder gehört nicht zu diesem Kundenkonto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsAccount.addresses](/frontend/referenz/module/wsAccount#\$wsaccount-addresses)
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.selectedShippingAddress](/frontend/referenz/module/wscheckout#\$wscheckout-selectedshippingaddress)
**Beispiel** das zeigt, wie eingeloggten Kunden ein Dropdown mit ihren gespeicherten Adressen angezeigt wird, über das sie eine Lieferadresse auswählen können.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myCheckoutShippingAddressSelect = $wsActions.create("CheckoutShippingAddressSelect") }}
```
***
### CheckoutSetDraftAddress
Mit dieser Aktion wird eine vom Kunden eingegebene Adresse vorläufig gespeichert, ohne dass die Eingaben sofort auf Vollständigkeit oder Korrektheit geprüft werden. Die Draft-Adresse wirkt sich dabei bereits auf die verfügbaren Versand- und Zahlungsarten aus, die auf Basis der Eingaben angepasst werden (relevant für den OnePage-Checkout).
Die Adresse gilt zunächst als Entwurf und wird erst durch [CheckoutCommitDraftAddress](#checkoutcommitdraftaddress) als verbindliche Checkout-Adresse übernommen. Der Adresstyp wird direkt im Aktionsnamen angegeben (`bill` oder `shipping`).
**Anwendungsbeispiel**
Nutzbar im OnePage-Checkout, um die eingegebene Adresse laufend zwischenzuspeichern, ohne den Kunden sofort mit Validierungsfehlern zu konfrontieren. Die eigentliche Prüfung der Adresse erfolgt erst beim Klick auf “Jetzt kaufen” über [CheckoutCommitDraftAddress](#checkoutcommitdraftaddress).
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `address.(fieldname)` | Die einzelnen Felder der Adresse, beispielsweise `address.firstName` oder `address.street`. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.draftBillAddressId](/frontend/referenz/module/wscheckout#\$wscheckout-draftbilladdressid)
* [\$wsCheckout.draftShippingAddressId](/frontend/referenz/module/wscheckout#\$wscheckout-draftshippingaddressid)
**Beispiel** das zeigt, wie eine Rechnungsadresse als Entwurf zwischengespeichert wird, ohne sie sofort zu validieren.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionSetDraftBillAddress = $wsActions.create("CheckoutSetDraftAddress:bill") }}
```
***
### CheckoutCommitDraftAddress
Mit dieser Aktion wird ein zuvor per [CheckoutSetDraftAddress](#checkoutsetdraftaddress) gespeicherter Adressentwurf validiert und als Checkout-Adresse übernommen. Das Verhalten unterscheidet sich je nach Bestelltyp:
* Gastbestellung - die eingegebene Adresse wird geprüft und, sofern gültig, direkt für den Checkout übernommen.
* Bestellung mit Kundenkonto - die eingegebene Adresse wird geprüft und, sofern gültig, als neue Adresse im Kundenkonto angelegt und gleichzeitig für den aktuellen Checkout ausgewählt.
Sind die Daten fehlerhaft oder unvollständig, schlägt die Validierung fehl und der Entwurf bleibt erhalten, sodass der Kunde seine Eingaben korrigieren kann. Der Adresstyp wird direkt im Aktionsnamen angegeben (`bill` oder `shipping`).
Diese Aktion bildet zusammen mit [CheckoutSetDraftAddress](#checkoutsetdraftaddress) den typischen Adress-Workflow im OnePage-Checkout:
[CheckoutSetDraftAddress](#checkoutsetdraftaddress) speichert die Eingaben laufend zwischen (ohne Validierung), `CheckoutCommitDraftAddress` schließt den Prozess ab.
**Anwendungsbeispiel**
Nutzbar als abschließender Schritt im OnePage-Checkout. Der Kunde hat seine Adresse bereits eingegeben und erst beim Klick auf “Jetzt kaufen” wird geprüft, ob alle Angaben korrekt und vollständig sind.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `address.(fieldname)` | Die einzelnen Felder der Adresse, beispielsweise `address.firstName` oder `address.street`. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `addressCheckFailed` | Fehler in den Adressdaten. Wird über Sub-Codes konkretisiert:
`minlen` = zu wenig Zeichen
`maxlen` = zu viele Zeichen
`numeric` = ungültige Zeichen
`country` = Land nicht konfiguriert
`zip` = Postleitzahl fehlerhaft |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.isValidShippingAddress()](/frontend/referenz/module/wscheckout#\$wscheckout-isvalidshippingaddress)
* [\$wsCheckout.isValidBillAddress()](/frontend/referenz/module/wscheckout#\$wscheckout-isvalidbilladdress)
**Beispiel** das zeigt, wie ein Rechnungsadress-Entwurf validiert und als verbindliche Checkout-Adresse übernommen wird. Bei fehlerhaften Eingaben bleibt der Entwurf erhalten und Fehler werden ausgegeben.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionCommitDraftBillAddress = $wsActions.create("CheckoutCommitDraftAddress:bill") }}
{{ include "components/errorAlert.htm" with $myAction = $myActionCommitDraftBillAddress }}
```
***
### CheckoutUseSameShippingAddress
Mit dieser Aktion wird festgelegt, dass die Lieferung an dieselbe Adresse wie die Rechnungsadresse erfolgen soll. Eine zuvor eingegebene oder ausgewählte abweichende Lieferadresse wird dadurch nicht gelöscht, aber für den Checkout nicht mehr berücksichtigt.
**Anwendungsbeispiel**
Nutzbar, um dem Kunden beispielsweise per Checkbox die Möglichkeit zu geben, Rechnungs- und Lieferadresse mit einem Klick gleichzusetzen, ohne erneute Eingabe.
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.useAlternativeShippingAddress](/frontend/referenz/module/wscheckout#\$wscheckout-usealternativeshippingaddress)
**Beispiel** das zeigt, wie die Aktion über ein verstecktes Formular ausgelöst wird, das per JavaScript an eine Checkbox gekoppelt werden kann.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionCheckoutUseSameShippingAddress = $wsActions.create("CheckoutUseSameShippingAddress") }}
```
***
### CheckoutUseDifferentShippingAddress
Mit dieser Aktion wird eine abweichende Lieferadresse für den Checkout aktiviert. Sobald sie ausgelöst wurde, wird der Bereich zur Auswahl oder Eingabe einer separaten Lieferadresse relevant. Die Aktion kehrt den Effekt von [CheckoutUseSameShippingAddress](#checkoutusesameshippingaddress) um.
**Anwendungsbeispiel**
Nutzbar, wenn der Kunde eine Bestellung an eine andere Adresse liefern lassen möchte, beispielsweise direkt an eine Filiale.
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.useAlternativeShippingAddress](/frontend/referenz/module/wscheckout#\$wscheckout-usealternativeshippingaddress)
**Beispiel** das zeigt, wie die Aktion über ein verstecktes Formular ausgelöst wird, das per JavaScript an eine Checkbox gekoppelt werden kann.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionCheckoutUseDifferentShippingAddress = $wsActions.create("CheckoutUseDifferentShippingAddress") }}
```
***
### CheckoutAccountTypeSelect
Mit dieser Aktion wird der Kontotyp für den aktuellen Bestellvorgang festgelegt. Der gewählte Typ bestimmt, welche Schritte im Checkout-Prozess angezeigt werden.
**Anwendungsbeispiel**
Nutzbar auf der Login-Seite im Checkout-Kontext, um dem Kunden die Möglichkeit zu geben, als Gast zu bestellen, ohne ein Konto anlegen zu müssen.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `accountType` | Der gewünschte Kontotyp. Mögliche Werte: - `guest` - Gastkonto - `new` - Neues Kundenkonto - `registered` - Registrierter Kunde |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `invalidAccountType` | Der angegebene Kontotyp ist ungültig. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.accountType](/frontend/referenz/module/wscheckout#\$wscheckout-accounttype)
**Beispiel** das zeigt, wie der Kontotyp auf “`guest`” gesetzt wird, um eine Gastbestellung zu ermöglichen.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionCheckoutAccountTypeSelect = $wsActions.create("CheckoutAccountTypeSelect") }}
```
***
### CheckoutSetGuestEmail
Mit dieser Aktion wird die E-Mail-Adresse für eine Gastbestellung gesetzt. Sie ist nur relevant, wenn der Kontotyp auf “`guest`” gesetzt wurde.
**Anwendungsbeispiel**
Nutzbar im Checkout, wenn ein Kunde als Gast bestellen möchte und dafür seine E-Mail-Adresse angeben muss.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `guestEmail` | Die E-Mail-Adresse des Gastkunden. |
**Fehlercodes**
| **Code** | **Beschreibung** |
| - | - |
| `missingEmail` | Parameter `guestEmail` fehlt. |
| `emailCheckFailed` | Parameter `guestEmail` enthält keine gültige E-Mail-Adresse. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.guestMail](/frontend/referenz/module/wscheckout#\$wscheckout-guestmail)
* [\$wsCheckout.accountType](/frontend/referenz/module/wscheckout#\$wscheckout-accounttype)
**Beispiel** das zeigt, wie ein Gastkunde seine E-Mail-Adresse im Checkout eingibt, inklusive Fehlerausgabe bei ungültiger Eingabe.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionCheckoutSetGuestEmail = $wsActions.create("CheckoutSetGuestEmail") }}
```
***
### CheckoutShippingMethodUpdate
Mit dieser Aktion wird die Versandart für den aktuellen Bestellvorgang gesetzt.
**Anwendungsbeispiel**
Nutzbar im Checkout, um dem Kunden eine Liste der verfügbaren Versandarten anzuzeigen, aus der er eine auswählen kann.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `shippingMethodId` | Die ID der Versandart, die ausgewählt werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingShippingMethodId` | Parameter `shippingMethodId` fehlt. |
| `invalidShippingMethodId` | Die angegebene Versandart ist nicht verfügbar. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.selectedShippingMethod](/frontend/referenz/module/wscheckout#\$wscheckout-selectedshippingmethod)
* [\$wsCheckout.isValidShippingMethod()](/frontend/referenz/module/wscheckout#\$wscheckout-isvalidshippingmethod)
* [\$wsCheckout.problems.shippingMethod](/frontend/referenz/module/wscheckout#\$wscheckout-problems)
**Beispiel** das zeigt, wie alle verfügbaren Versandarten als Auswahlliste dargestellt werden, wobei nicht verfügbare Optionen deaktiviert sind.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionCheckoutShippingMethodUpdate = $wsActions.create("CheckoutShippingMethodUpdate") }}
```
***
### CheckoutConfirm
Mit dieser Aktion wird die Bestellung verbindlich abgeschickt. Sie ist der abschließende Schritt im Checkout-Prozess und setzt voraus, dass alle erforderlichen Angaben (Adresse, Zahlungsart und Versandart) vollständig und gültig sind.
**Anwendungsbeispiel**
Nutzbar als “Jetzt kaufen”-Button auf der Bestellübersichtsseite, über den der Kunde die Bestellung verbindlich aufgibt.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt und es ist keine Gast-E-Mail vorhanden. |
| `invalidCheckout` | Der Checkout ist nicht vollständig oder enthält ungültige Angaben. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.isValid](/frontend/referenz/module/wscheckout#\$wscheckout-isvalid)
* [\$wsCheckout.problems](/frontend/referenz/module/wscheckout#\$wscheckout-problems)
* [\$wsCheckout.isExpressCheckoutLocked](/frontend/referenz/module/wscheckout#\$wscheckout-isexpresscheckoutlocked)
**Beispiel** das zeigt, wie die Bestellung über einen Button verbindlich abgeschickt wird, sofern der Kunde eingeloggt oder als Gast identifiziert ist.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionCheckoutConfirm = $wsActions.create("CheckoutConfirm") }}
```
***
### RefreshPaymentStatus
Mit dieser Aktion wird der Status einer Zahlung manuell aktualisiert. Die Aktion fragt den aktuellen Stand ab und gibt ihn im JSON-Format zurück.
Eine Erfolgsmeldung des Zahlungsdienstleisters bedeutet dabei noch nicht, dass die Zahlung im Shop gültig ist. Meldet PayPal beispielsweise eine erfolgreiche Zahlung, muss der Shop diese nicht zwingend akzeptieren. Ist die 3DS-Prüfung nicht durchgelaufen, lehnt der Shop die Zahlung aus Sicherheitsgründen ab. Außerdem kann die Zahlung beim Einzug des Betrags noch in einen Fehler laufen. Der zurückgegebene Status ist deshalb die Bewertung des Shops und nicht die Rückmeldung des Zahlungsdienstleisters.
**Anwendungsbeispiel**
Nutzbar auf der Wartseite einer Online-Zahlung. Der Kunde darf erst dann auf die Bestellbestätigung geführt werden, wenn diese Aktion die Zahlung als fehlerfrei abgeschlossen meldet. Meldet sie einen Fehler oder einen Abbruch, gehört der Kunde in die Fehlerbehandlung.
**Antwort**
Die Antwort enthält immer das Feld `paymentStatus`.
```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
"paymentStatus": "pending"
}
```
| **Wert** | **Bedeutung** |
| - | - |
| `unknown` | Es gibt keine Zahlung, deren Status abgefragt werden kann. |
| `redirected` | Der Kunde wurde zum Zahlungsdienstleister weitergeleitet, ein Ergebnis liegt noch nicht vor. |
| `pending` | Die Zahlung wurde angenommen, ist aber noch in Bearbeitung. |
| `finished` | Die Zahlung ist abgeschlossen und vom Shop akzeptiert. |
| `canceledByUser` | Die Zahlung wurde vom Kunden abgebrochen. |
| `canceledByAdmin` | Die Zahlung wurde im Backend abgebrochen. |
| `error` | Bei der Zahlung ist ein Fehler aufgetreten oder der Shop hat sie abgelehnt. |
Die Zustände entsprechen den Zahlungsstatus, die auch die REST-API für [Bestellungen](/schnittstellen/admin-interface-api/api-referenz-bestellungen) und Transaktionen verwendet. Dort werden sie numerisch geführt, in dieser Antwort als Text. Neben den hier aufgeführten Werten kann die Transaktion weitere Status annehmen, beispielsweise nach einer Rückerstattung im Backend. Behandeln Sie unbekannte Werte im Template daher als offenen Status.
**Fehler in der Antwort**
Hat `paymentStatus` den Wert `error`, enthält die Antwort zusätzlich das Feld `errors` mit einer Liste der aufgetretenen Fehler.
```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
"paymentStatus": "error",
"errors": [
{
"code": "",
"subCode": "",
"field": "",
"text": "",
"details": {}
}
]
}
```
| **Feld** | **Typ** | **Beschreibung** |
| - | - | - |
| `code` | string | Fehlercode. |
| `subCode` | string | Optionaler Code zur genaueren Bestimmung von `code`. |
| `field` | string | Feld, in dem der Fehler aufgetreten ist. Bei Zahlungsfehlern ohne Feldbezug leer. |
| `text` | string | Anzeigetext des Fehlers. |
| `details` | object | Zusätzliche Angaben zum Fehler. |
Die Liste ist bisher immer leer. Die Befüllung wird erst später umgesetzt, das Format steht aber bereits fest und kann im Frontend berücksichtigt werden. Werten Sie den Fehlerfall deshalb über den Statuswert `error` aus und nicht über die Länge der Liste.
**Zugehörige Module, Variablen & Methoden**
* [\$wsActions](/frontend/referenz/module/wsactions)
* [API-Referenz Bestellungen](/schnittstellen/admin-interface-api/api-referenz-bestellungen)
***
### CheckoutSetFreeFields
Mit dieser Aktion werden die freien Checkout-Felder gesetzt, beispielsweise die Zustimmung zu den AGB oder ein Kommentarfeld. Die Aktion wird typischerweise zusammen mit `CheckoutConfirm` auf der Bestellübersichtsseite eingesetzt.
**Anwendungsbeispiel**
Nutzbar auf der Bestellübersichtsseite, um dem Kunden beispielsweise eine Checkbox zur Zustimmung der AGB anzuzeigen, die vor dem Abschicken der Bestellung akzeptiert werden muss.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `freeFields.(id).value` | Der Wert des freien Felds, beispielsweise `freeFields.agb.value` für die AGB-Checkbox. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingRequiredField` | Ein Pflichtfeld wurde nicht ausgefüllt. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.freeFields](/frontend/referenz/module/wscheckout#\$wscheckout-freefields)
**Beispiel** das zeigt, wie eine AGB-Checkbox als freies Checkout-Feld eingebunden wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionSetFreeFields = $wsActions.create("CheckoutSetFreeFields") }}
```
***
### CheckoutSetPaymentFields
Mit dieser Aktion werden die Zusatzfelder der gewählten Zahlungsart gespeichert. Beispielsweise können für PayPal "Kauf auf Rechnung" das Geburtsdatum und die Telefonnummer erfasst werden. Welche Felder es gibt, wird in der Konfiguration unter `payment.paymentField` festgelegt. Die aktuell sichtbaren Felder einer Zahlungsart stehen im Template unter `$wsConfig.payments` im Eintrag `fields` bereit.
**Anwendungsbeispiel**
Nutzbar auf der Zahlungsarten-Seite oder in der Bestellübersicht, um die Zusatzfelder direkt unter der gewählten Zahlungsart abzufragen.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `paymentFields.(name)` | Wert des Zusatzfeldes mit dem technischen Namen `(name)`, beispielsweise `paymentFields.bday`. Datumsfelder erwarten das Format `JJJJ-MM-TT`. Bei Checkboxen gilt jeder nicht leere Wert als gesetzt. Bei Auswahllisten muss der Wert einem `value` aus den Optionen entsprechen. |
Die Aktion verarbeitet nur die Felder der aktuell gewählten Zahlungsart, und zwar nur diejenigen, deren Anzeigebedingungen erfüllt sind. Jedes dieser Felder übernimmt den entsprechenden Wert aus der Anfrage. Fehlt ein Feld in der Anfrage, speichert der Shop dafür einen leeren Wert bzw. bei Checkboxen den Wert `false` . Schicken Sie deshalb alle sichtbaren Zusatzfelder einer Zahlungsart in einem gemeinsamen Formular ab.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `requiredPaymentFieldEmpty` | Ein Pflichtfeld ist leer. |
| `requiredPaymentCheckboxUnchecked` | Eine Pflicht-Checkbox ist nicht gesetzt. |
| `invalidSelectValue` | Der Wert einer Auswahlliste steht nicht unter den Optionen. Der Wert wird nicht übernommen. |
| `fieldCheckFailed` | Eine Prüfung aus `validations` ist fehlgeschlagen. `subCode` nennt die Prüfung, beispielsweise `dataChecker.regex`. Der Text stammt aus [`general.dataCheckerValidationErrors`](/konfiguration/general-allgemeine-shopeinstellungen#generaldatacheckervalidationerrors---fehlertexte-für-feldprüfungen). |
Ob die Aktion diese Fehler schon beim Speichern meldet, steuert [`checkout.fieldErrorVisibility`](/konfiguration/checkout-bestellablauf#fehleranzeige-im-checkout) mit `showMissingBeforeSubmit` und `showInvalidBeforeSubmit`. Beim Bestellabschluss mit `CheckoutConfirm` prüft der Shop die Zusatzfelder in jedem Fall erneut und bricht bei leeren Pflichtfeldern mit `requiredPaymentFieldEmpty` bzw. `requiredPaymentCheckboxUnchecked` ab. Die Fehlertexte sind unter [`actions.checkoutSetPaymentFields`](/konfiguration/actions-fehlertexte-e-mails/actions-warenkorb-checkout#actionscheckoutsetpaymentfields---zusatzfelder-der-zahlungsart) und [`actions.checkoutConfirm`](/konfiguration/actions-fehlertexte-e-mails/actions-warenkorb-checkout#actionscheckoutconfirm---bestellung-abschließen) konfiguriert.
**Zugehörige Module, Variablen & Methoden**
* [\$wsConfig.payments](/frontend/referenz/module/wsconfig#wsconfigpayments)
* [\$wsCheckout.selectedPayment](/frontend/referenz/module/wscheckout)
* [payment.paymentField](/konfiguration/payment-zahlungsmethoden#paymentpaymentfield---zusatzfelder-für-zahlungsarten)
**Beispiel** das zeigt, wie die Zusatzfelder der gewählten Zahlungsart je nach Feldtyp ausgegeben und bei jeder Änderung gespeichert werden. Leere Felder werden mit dem gemerkten Wert aus dem Kundenkonto vorbelegt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $paymentFieldAction = $wsActions.create("CheckoutSetPaymentFields") }}
{{ foreach $payment in $wsConfig.payments }}
{{ if $payment.id == $wsCheckout.selectedPayment }}
{{ /if }}
{{ /foreach }}
```
Ändert sich eine Adresse oder ein anderes Zusatzfeld, kann sich die Anzahl der sichtbaren Felder ändern, weil ihre Anzeigebedingungen davon abhängen. Laden Sie in diesem Fall den Bereich mit den Zusatzfeldern neu, beispielsweise nach jedem automatischen Absenden des Formulars.
***
### CheckoutSetCustomerData
Mit dieser Aktion werden zusätzliche Kundendaten im Checkout gesetzt. Die Felder werden dynamisch aus der Konfiguration geladen und können gruppiert oder ungruppiert vorliegen.
**Anwendungsbeispiel**
Nutzbar im Checkout, um konfigurierte Kundendaten-Felder (beispielsweise Firmenname oder Telefon) abzufragen, die über die Standardadresse hinausgehen.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `(dynamisch)` | Die Felder werden aus [\$wsCheckout.customerData](/frontend/referenz/module/wscheckout#\$wscheckout-customerdata) geladen und variieren je nach Shop-Konfiguration. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.customerData](/frontend/referenz/module/wscheckout#\$wscheckout-customerdata)
* [\$wsCheckout.customerData.fieldGroups](/frontend/referenz/module/wscheckout#\$wscheckout-customerdata-fieldgroups)
**Beispiel** das zeigt, wie gruppierte Kundendaten-Felder dynamisch gerendert und Fehler feldspezifisch ausgegeben werden:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $setCustomerDataAction = $wsActions.create("CheckoutSetCustomerData") }}
```
***
### CheckoutPseudoCCSelect
Mit dieser Aktion wählt der Kunde eine seiner gespeicherten Pseudo-Kreditkarten für den aktuellen Bestellvorgang aus. Die Aktion ist ausschließlich für die Computop-Kreditkarten-Integration relevant.
**Anwendungsbeispiel**
Nutzbar im Checkout, wenn der Kunde eine zuvor hinterlegte Kreditkarte verwenden möchte, ohne die Kartendaten erneut einzugeben. Der Wert `0` steht für “keine gespeicherte Karte verwenden”.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `pseudoCCId` | Die ID der gespeicherten Pseudo-Kreditkarte. Der Wert `0` wählt keine Karte aus. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.selectedPseudoCC](/frontend/referenz/module/wscheckout#\$wscheckout-selectedpseudocc)
**Beispiel** das zeigt, wie gespeicherte Kreditkarten zur Auswahl angezeigt werden, inklusive der Option, keine Karte zu verwenden.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myAction = $wsActions.create("CheckoutPseudoCCSelect") }}
```
***
### CheckoutNewsletterSubscribe
Mit dieser Aktion wird ein Kunde während des Bestellvorgangs für den Newsletter angemeldet. Sie funktioniert analog zur Aktion [NewsletterSubscribe](/frontend/referenz/aktionen/newsletter). Parameter, Fehlercodes und das Feldübergabe-Verhalten sind identisch.
**Anwendungsbeispiel**
Nutzbar im Checkout, um Kunden während des Bestellvorgangs die Möglichkeit zu geben, sich für den Newsletter anzumelden, beispielsweise über eine Checkbox auf der Bestellübersichtsseite.
**Parameter**
| Name | Beschreibung |
| - | - |
| `email` | Die E-Mail-Adresse, die für den Newsletter angemeldet werden soll. |
| `targetGroupId.(id)` | Optionale Zielgruppen-ID, für die der Kunde angemeldet werden soll. |
**Fehlercodes**
| Fehlercode | Beschreibung |
| - | - |
| `missingEmail` | Parameter `email` fehlt. |
| `emailCheckFailed` | Die angegebene E-Mail-Adresse ist ungültig. |
| `accountAlreadyExists` | Die E-Mail-Adresse ist bereits für den Newsletter angemeldet. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsNewsletter](/frontend/referenz/module/wsnewsletter)
* [\$wsNewsletter.getTargetGroups()](/frontend/referenz/module/wsnewsletter#\$wsnewsletter-gettargetgroups)
**Beispiel** das zeigt, wie ein Kunde im Checkout eine Zielgruppe auswählt und sich für den Newsletter anmeldet.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionCheckoutNewsletterSubscribe = $wsActions.create("CheckoutNewsletterSubscribe") }}
```
***
### CheckoutStoreIdSelect
Mit dieser Aktion wählt der Kunde einen Markt als Abholort für den aktuellen Bestellvorgang aus. Die Aktion ist nur relevant, wenn eine Versandart vom Typ `pickup` ausgewählt wurde. Bei der Auswahl wird geprüft, ob alle Produkte im gewählten Markt verfügbar sind. Ist das nicht der Fall, wird die Aktion nicht ausgeführt und es wird ein Fehler zurückgegeben.
Wurde kein Markt ausgewählt, wird standardmäßig der Markt aus der allgemeinen [Session-Auswahl](/frontend/referenz/aktionen/stores#selectstore) verwendet.
**Anwendungsbeispiel**
Nutzbar, wenn der Kunde eine Bestellung direkt in einem Markt abholen möchte und im Checkout aus den verfügbaren Click & Collect-Märkten wählen soll.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `reservationFailed` | Die Artikel sind im gewählten Markt nicht verfügbar. Details zum betroffenen Produkt werden über `error.details.productId` zurückgegeben. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsCheckout.selectedStoreID](/frontend/referenz/module/wscheckout#\$wscheckout-selectedstoreid)
* [\$wsCheckout.selectedShippingMethod](/frontend/referenz/module/wscheckout#\$wscheckout-selectedshippingmethod)
* [\$wsStores](/frontend/referenz/module/wsstores)
* [\$wsStores.loadAllStores()](/frontend/referenz/module/wsstores#\$wsstores-loadallstores)
* [\$wsConfig.shippingMethods](/frontend/referenz/module/wsconfig#\$wsconfig-shippingmethods)
**Beispiel,** das für jede Versandart vom Typ `pickup` ein Dropdown mit allen Click & Collect-fähigen Märkten zeigt. Es setzt den gewählten Markt per `CheckoutStoreIdSelect` als Abholort, inklusive Fehlerbehandlung bei nicht verfügbaren Artikeln im gewählten Markt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionCheckoutStoreIdSelect = $wsActions.create("CheckoutStoreIdSelect") }}
{{ foreach $myShipping in $wsConfig.shippingMethods }}
{{ if $wsCheckout.selectedShippingMethod == $myShipping.id and $myShipping.type == "pickup" }}
{{ if $myActionCheckoutStoreIdSelect.error }}
{{ foreach $myError in $myActionCheckoutStoreIdSelect.errors }}
{{ if $myError.code == "reservationFailed" }}
Artikel im Store nicht verfügbar: {{= $myError.details.productId }}
{{ /if }}
{{ /foreach }}
{{ /if }}
{{ /if }}
{{ /foreach }}
```
***
## Weiterführende Links
* [\$wsActions](/frontend/referenz/module/wsactions)
* [\$wsAccount](/frontend/referenz/module/wsAccount)
* [\$wsCheckout](/frontend/referenz/module/wscheckout)
* [\$wsStores](/frontend/referenz/module/wsstores)
* [payment - Zahlungsmethoden](/konfiguration/payment-zahlungsmethoden)
# Consent
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/consent
Consent-Aktionen für den Cookie-Banner: Einwilligung des Nutzers zu nicht-essenziellen Cookies und Diensten setzen oder nachträglich ändern.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich Consent beschrieben. Mit diesen Aktionen kann die Zustimmung des Nutzers zu nicht-essenziellen Cookies und Diensten gesetzt oder geändert werden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `ConsentChange` | Setzt oder ändert die Zustimmung zu nicht-essenziellen Cookies und Diensten. |
***
## Aktionen
### ConsentChange
Mit dieser Aktion wird die Zustimmung des Nutzers zu nicht-essenziellen Cookies gesetzt oder geändert. Die Zustimmung kann auf oberster Ebene (gesamtes Consent-Objekt), auf Gruppenebene oder auf Ebene einzelner Dienste innerhalb einer Gruppe gesteuert werden.
**Anwendungsbeispiel**\
Nutzbar, um z.B. in einem Cookie-Banner dem Nutzer die Möglichkeit zu geben, seine Zustimmung für alle Cookies auf einmal, für bestimmte Gruppen (z.B. “Marketing”, “Statistik”) oder für einzelne Dienste (z.B. “Google Analytics”) gezielt zu erteilen oder zu widerrufen.
**Parameter**
| **Parameter** | **Beschreibung** |
| - | - |
| `consent` | Setzt die Zustimmung auf oberster Ebene für alle nicht-essenziellen Cookies. |
| `groups.` | Setzt die Zustimmung für eine bestimmte Consent-Gruppe. `` steht für den Namen der jeweiligen Gruppe. |
| `groups..services.` | Setzt die Zustimmung für einen einzelnen Dienst innerhalb einer Gruppe. `` steht für den Namen des jeweiligen Dienstes. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `invalidGroup` | Die angegebene Gruppe existiert nicht oder ist ungültig. |
| `invalidService` | Der angegebene Dienst existiert nicht oder ist ungültig. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsConsent](/frontend/referenz/module/wsconsent)
* [\$wsConsent.groups](/frontend/referenz/module/wsconsent#\$wsconsent-groups)
* [\$wsConsent.services](/frontend/referenz/module/wsconsent#\$wsconsent-services)
**Beispiel** das zeigt, wie in einem Cookie-Banner die Zustimmung pro Gruppe und pro Dienst über Checkboxen gesteuert wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionConsentChange = $wsActions.create("ConsentChange") }}
```
# DirectOrder
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/directorder
DirectOrder-Aktionen für die Direktbestellung: Produkte per Artikelnummer in eine Bestellliste eintragen, ändern und in den Warenkorb übernehmen.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich Direktbestellung beschrieben. Mit diesen Aktionen können Produkte per Artikelnummer in die Bestellschein-Liste der Session eingetragen, geändert und wieder entfernt werden. Außerdem steuern sie die Anzahl der Eingabezeilen.
Die DirectOrder-Aktionen legen nichts in den Warenkorb. Die Übernahme der erfassten Positionen ist ein eigener Schritt, für den die Aktion `BasketItemAdd` verwendet wird. Ein vollständiges Beispiel hierfür finden Sie unter [Positionen in den Warenkorb übernehmen](/frontend/referenz/module/wsdirectorder#positionen-in-den-warenkorb-übernehmen).
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `DirectOrderAdd` | Trägt ein Produkt per Artikelnummer in die Bestellschein-Liste ein oder erhöht die Menge einer vorhandenen Position. |
| `DirectOrderUpdate` | Setzt die Menge einer Position in der Bestellschein-Liste. Ist die Position noch nicht vorhanden, wird sie angelegt. |
| `DirectOrderDelete` | Entfernt eine Position aus der Bestellschein-Liste. |
| `DirectOrderAddLines` | Fügt `refreshedNumber` Eingabezeilen hinzu, höchstens bis `maximalNumber`. |
| `DirectOrderDeleteLines` | Entfernt `refreshedNumber` Eingabezeilen, nie unter `initialNumber`. |
***
## Aktionen
### DirectOrderAdd
Mit dieser Aktion wird ein Produkt anhand seiner Artikelnummer in die Bestellschein-Liste eingetragen. Ist das Produkt bereits in der Liste enthalten, addiert die Aktion die neue Menge zur bestehenden Menge. Nach erfolgreicher Ausführung wird die Position in `$wsDirectOrder.items` gesetzt.
Die Artikelnummer stammt entweder aus dem Feld `id` oder aus den konfigurierten Artikelnummern-Feldern. Letztere werden nur ausgewertet, wenn das Feld `id` leer ist.
**Anwendungsbeispiel**\
Nutzbar auf der Direktbestellseite, auf der Kunden Produkte schnell per Artikelnummer suchen und zur Bestellliste hinzufügen können, ohne die Produktdetailseite aufrufen zu müssen.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `id` | Die Artikelnummer, Produktnummer, EAN oder ISBN des Produkts. |
| `quantity` | **Pflichtfeld**
Die Menge. Fehlt sie, meldet die Aktion `missingQuantity`. |
| Namen der Artikelnummern-Felder | Die Eingabefelder, die unter [`checkout.directOrder`](/konfiguration/checkout-bestellablauf#checkoutdirectorder---onlinebestellschein) in `itemNumberFields` konfiguriert sind, beispielsweise `firstField`. Werden nur ausgewertet, wenn `id` leer ist. |
| `insert` | Das [Werbemittelkennzeichen](/frontend/funktionsubersicht/werbemittelkennzeichnung) der Position. Wird nur verwendet, wenn der Shop kein Kennzeichen aus der eingegebenen Artikelnummer abgetrennt hat. |
**Fehler**
| **Fehlerfeld** | **Fehlercodes** |
| - | - |
| `errorsByField.id` | `missingId`, `invalidId`, `productHasNoVariants`, `variantDoesNotExist`, `baseProductCanNotBeChosen` |
| `errorsByField.quantity` | `missingQuantity`, `invalidQuantity` |
| `errorsByField.` | `itemNumberCheckFailed`, `missingId` bei einem leeren Pflichtfeld |
Die Fehlertexte und die genaue Zuordnung stehen unter [actions.directOrder](/konfiguration/actions-fehlertexte-e-mails/actions-warenkorb-checkout#actionsdirectorder---direktbestellung).
**Zugehörige Module, Variablen & Methoden**
* [\$wsDirectOrder](/frontend/referenz/module/wsdirectorder)
* [\$wsDirectOrder.items](/frontend/referenz/module/wsdirectorder#\$wsdirectorder-items)
* [\$wsDirectOrder.currentLines](/frontend/referenz/module/wsdirectorder#\$wsdirectorder-currentlines)
**Beispiel** das zeigt, wie ein Produkt über ein Artikelnummer-Eingabefeld zur Direktbestellliste hinzugefügt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionDirectOrderAdd = $wsActions.create("DirectOrderAdd", tag=string($myDirectOrderProduct)) }}
```
***
### DirectOrderUpdate
Mit dieser Aktion wird die Menge einer Position in der Bestellschein-Liste gesetzt. Im Unterschied zu `DirectOrderAdd` wird die Menge nicht addiert, sondern ersetzt. Fehlt die Produktnummer noch in der Liste, wird die Position durch die Aktion angelegt.
**Anwendungsbeispiel**\
Nutzbar auf der Direktbestellseite, wenn ein Kunde die Menge eines bereits eingetragenen Produkts anpassen möchte.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `id` | Die Produktnummer der Position. Alternativ die Namen der Artikelnummern-Felder wie bei `DirectOrderAdd`. |
| `quantity` | **Pflichtfeld**
Die neue Menge des Produkts. |
| `insert` | Das [Werbemittelkennzeichen](/frontend/funktionsubersicht/werbemittelkennzeichnung) der Position, wie bei `DirectOrderAdd`. |
**Fehler**
Die Aktion kann dieselben Fehler melden wie `DirectOrderAdd`.
**Zugehörige Module, Variablen & Methoden**
* [\$wsDirectOrder](/frontend/referenz/module/wsdirectorder)
* [\$wsDirectOrder.items](/frontend/referenz/module/wsdirectorder#\$wsdirectorder-items)
**Beispiel** das zeigt, wie die Menge einer Position in der Direktbestellliste über ein Eingabefeld aktualisiert wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionDirectOrderUpdate = $wsActions.create("DirectOrderUpdate", tag=string($myDirectOrderProduct)) }}
```
***
### DirectOrderDelete
Mit dieser Aktion wird ein Produkt aus der Direktbestellliste entfernt.
**Anwendungsbeispiel**\
Nutzbar auf der Direktbestellseite, wenn ein Kunde ein Produkt aus der Bestellliste entfernen möchte.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `id` | Die vom Shop ermittelte Produktnummer aus `$wsDirectOrder.items[…].id`, nicht die vom Kunden eingegebene Artikelnummer. |
**Fehler**
| **Fehlerfeld** | **Fehlercodes** |
| - | - |
| `errorsByField.id` | `invalidId`, wenn `id` fehlt oder leer ist |
**Zugehörige Module, Variablen & Methoden**
* [\$wsDirectOrder](/frontend/referenz/module/wsdirectorder)
* [\$wsDirectOrder.items](/frontend/referenz/module/wsdirectorder#\$wsdirectorder-items)
**Beispiel** das zeigt, wie ein Produkt über einen Button aus der Direktbestellliste entfernt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionDirectOrderDelete = $wsActions.create("DirectOrderDelete", tag=string($myDirectOrderProduct)) }}
```
***
### DirectOrderAddLines
Durch diese Aktion werden dem Bestellschein weitere Eingabezeilen hinzugefügt, sodass der Kunde mehrere Produkte auf einmal eintragen kann. Die Anzahl legt `refreshedNumber` unter `checkout.directOrder` fest (Default `5`). Die Gesamtzahl der Zeilen steigt dabei höchstens bis `maximalNumber`.
**Anwendungsbeispiel**\
Nutzbar auf der Direktbestellseite, wenn ein Kunde mehr Produkte eintragen möchte als aktuell Zeilen vorhanden sind.
**Zugehörige Module, Variablen & Methoden**
* [\$wsDirectOrder](/frontend/referenz/module/wsdirectorder)
* [\$wsDirectOrder.currentLines](/frontend/referenz/module/wsdirectorder#\$wsdirectorder-currentlines)
**Beispiel** das zeigt, wie über einen Button eine neue Eingabezeile zur Direktbestellliste hinzugefügt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionDirectOrderAddLines = $wsActions.create("DirectOrderAddLines") }}
```
***
### DirectOrderDeleteLines
Mit dieser Aktion werden die Eingabezeilen aus dem Bestellschein entfernt. Ihre Anzahl wird durch `refreshedNumber` festgelegt. Die Gesamtzahl der Zeilen sinkt dabei jedoch nie unter `initialNumber`.
**Anwendungsbeispiel**\
Nutzbar auf der Direktbestellseite, wenn ein Kunde zu viele Zeilen hinzugefügt hat und diese wieder entfernen möchte.
**Zugehörige Module, Variablen & Methoden**
* [\$wsDirectOrder](/frontend/referenz/module/wsdirectorder)
* [\$wsDirectOrder.currentLines](/frontend/referenz/module/wsdirectorder#\$wsdirectorder-currentlines)
**Beispiel** das zeigt, wie Eingabezeilen über einen Button entfernt werden. Der Button erscheint nur, wenn mehr Zeilen angezeigt werden als `initialNumber` vorgibt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsDirectOrder.currentLines > $wsConfig.directOrder.initialNumber }}
{{ var $myActionDirectOrderDeleteLines = $wsActions.create("DirectOrderDeleteLines") }}
{{ /if }}
```
# Inquiry
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/inquiry
Inquiry-Aktionen für Anfragen: Kontakt- und Anfrageformulare sowie Frage-zum-Produkt-Formulare im Frontend absenden und auswerten.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich `Inquiry` beschrieben. Mit diesen Aktionen können beispielsweise Kontakt- oder Anfrageformulare abgesendet werden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `InquirySend` | Sendet ein Anfrage-Formular mit den angegebenen Parametern ab. |
| `InquiryCheck` | Prüft die Eingaben eines Formulars, ohne es abzusenden. |
***
## Aktionen
### InquirySend
Mit dieser Aktion wird ein Anfrage-Formular abgesendet. Dabei werden die übermittelten Eingaben geprüft und die Anfrage verarbeitet. Schlägt die Verarbeitung fehl, wird ein entsprechender Fehler zurückgegeben, sodass der Nutzer seine Eingaben korrigieren kann.
**Anwendungsbeispiel**\
Nutzbar, um beispielsweise ein Kontaktformular auf einer Seite einzubinden, über das Kunden Anfragen stellen können. Nach dem Klick auf “Absenden” wird das Formular validiert und die Anfrage übermittelt.
**Parameter**
| **Parameter** | **Beschreibung** |
| - | - |
| `email` | Die E-Mail-Adresse des Absenders. Pflichtangabe. |
| `formId` | Die ID des abzusendenden Formulars. |
| `form.(fieldname)` | Die Werte der Formularfelder. Die Feldnamen entsprechen den Feldern des Formulars in der [Formularkonfiguration](/konfiguration/inquiry-formulare), beispielsweise `form.comment`. Werden keine Felder übergeben, gibt die Aktion den Fehlercode `emptyForm` zurück. |
**Fehler**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingEmail` | Es wurde keine E-Mail-Adresse angegeben. |
| `emailCheckFailed` | Die angegebene E-Mail-Adresse ist ungültig oder konnte nicht geprüft werden. |
| `emptyForm` | Das Formular enthält keine Eingaben. |
| `missingFormId` | Es wurde keine Formular-ID übergeben. |
| `invalidFormId` | Die angegebene Formular-ID ist nicht gültig. |
| `formCheckFailed` | Die Formularprüfung ist fehlgeschlagen. Ist ein Pflichtfeld leer, lautet der Sub-Code des Feldes `formCheck.required`. Der Fehlertext dazu stammt aus `missingField` in [actions - Formulare](/konfiguration/actions-fehlertexte-e-mails/actions-formulare). |
| `createInquiryFailed` | Die Anfrage konnte nicht erstellt werden. |
Wenn für das Formular eine Captcha-Prüfung konfiguriert ist und diese fehlschlägt, gibt die Aktion den Fehlercode `captchaFailed` zurück. Weitere Feldprüfungen des Formulars (beispielsweise die maximale Länge) melden ebenfalls `formCheckFailed` mit dem jeweiligen Sub-Code, beispielsweise `dataChecker.maxLength`.
**Zugehörige Module, Variablen & Methoden**
* [\$wsForm](/frontend/referenz/module/wsform)
* [\$wsForm.inquiryId](/frontend/referenz/module/wsform#\$wsform-inquiryid)
* [\$wsForm.loadType()](/frontend/referenz/module/wsform#\$wsform-loadtype)
* [\$wsForm.load()](/frontend/referenz/module/wsform#\$wsform-load)
**Beispiel,** das die Aktion erstellt, per Hidden-Input an das Formular bindet und nach dem Absenden auf Erfolg oder Fehler prüft.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cMyInquirySendAction = $wsActions.create('InquirySend') }}
```
***
### InquiryCheck
Mit dieser Aktion werden die Eingaben eines Formulars geprüft, ohne die Anfrage tatsächlich abzusenden. Die geprüften Feldwerte werden dabei in `$myField.value` zurückgeschrieben und können im Frontend wiederverwendet werden.
**Anwendungsbeispiel**\
Nutzbar, um Formulareingaben bereits vor dem endgültigen Absenden zu validieren und dem Nutzer direktes Feedback zu seinen Eingaben zu geben.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `form.(fieldname)` | Die aktuellen Werte der Formularfelder, anhand derer die Regeln des Formulars ausgewertet werden. |
**Fehlercodes**
Die Aktion selbst gibt keine Fehlercodes zurück. Sie speichert die übermittelten Feldwerte lediglich zur Auswertung der Regeln im Template ab. Die eigentliche Prüfung samt Fehlercodes erfolgt erst beim Absenden mit der Aktion `InquirySend`.
**Zugehörige Module, Variablen & Methoden**
* [\$wsForm](/frontend/referenz/module/wsform)
* [\$wsForm.loadType()](/frontend/referenz/module/wsform#\$wsform-loadtype)
**Beispiel** folgt.
# Inventory
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/inventory
Inventory-Aktionen für Lagerbestände: Produktreservierungen erneuern und Benachrichtigungen bei Wiederverfügbarkeit von Artikeln verwalten.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich `Inventory` beschrieben. Mit diesen Aktionen können Produktreservierungen erneuert und Benachrichtigungen bei Wiederverfügbarkeit verwaltet werden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `InventoryReserve` | Erneuert die Reservierung eines Produkts im Warenkorb. |
| `BackInStockActivateNotify` | Aktiviert eine Benachrichtigung, wenn ein Produkt wieder verfügbar ist. |
| `BackInStockDeactivateNotify` | Deaktiviert eine bestehende Wiedervorrätig-Benachrichtigung. |
***
## Aktionen
### InventoryReserve
Mit dieser Aktion wird die Reservierung eines Produkts im Warenkorb erneuert. Sie ist nur relevant, wenn die Reservierungsdauer eines Artikels abgelaufen ist und der Kunde die Reservierung verlängern möchte.
**Anwendungsbeispiel**\
Nutzbar auf der Warenkorbseite, wenn die Reservierungszeit eines Artikels abgelaufen ist und dem Kunden die Möglichkeit gegeben werden soll, die Reservierung zu erneuern.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `basketItemId` | Die ID des Warenkorb-Eintrags, dessen Reservierung erneuert werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingBasketItemId` | Parameter `basketItemId` fehlt. |
| `invalidBasketItemId` | Der Warenkorb-Eintrag existiert nicht oder gehört nicht zu diesem Warenkorb. |
| `reservationFailed` | Die Reservierung konnte nicht erneuert werden, z.B. weil das Produkt nicht mehr verfügbar ist. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsInventory](/frontend/referenz/module/wsinventory)
* [\$wsInventory.load()](/frontend/referenz/module/wsinventory#\$wsinventory-load)
* [\$wsInventory.loadReservation()](/frontend/referenz/module/wsinventory#\$wsinventory-loadreservation)
* [\$wsBasket.items](/frontend/referenz/module/wsbasket#\$wsbasket-items)
**Beispiel** das zeigt, wie einem Kunden bei abgelaufener Reservierung die Möglichkeit gegeben wird, diese über einen Button zu erneuern.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myReservation = $wsInventory.loadReservation($myProduct.id) }}
{{ if $myReservation and $myReservation.duration == 0 }}
{{ var $myActionInventoryReserve = $wsActions.create("InventoryReserve", tag=$myProduct.id) }}
{{ /if }}
```
***
### BackInStockActivateNotify
Mit dieser Aktion wird eine Benachrichtigung aktiviert, die den Kunden per E-Mail informiert, sobald ein ausverkauftes Produkt wieder verfügbar ist.
**Anwendungsbeispiel**\
Nutzbar auf der Produktdetailseite, wenn ein Produkt ausverkauft ist und der Kunde benachrichtigt werden möchte, sobald es wieder bestellbar ist.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `productId` | Die ID des Produkts, für das die Benachrichtigung aktiviert werden soll. |
| `email` | Die E-Mail-Adresse, an die die Benachrichtigung gesendet werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingProductId` | Parameter `productId` fehlt. |
| `missingEmail` | Parameter `email` fehlt. |
| `emailCheckFailed` | Die angegebene E-Mail-Adresse ist ungültig. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsInventory](/frontend/referenz/module/wsinventory)
* [\$wsAccount.backInStockList](/frontend/referenz/module/wsAccount#\$wsaccount-backinstocklist)
**Beispiel** das zeigt, wie ein Kunde eine Benachrichtigung für ein ausverkauftes Produkt aktivieren kann.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionBackInStockActivateNotify = $wsActions.create("BackInStockActivateNotify") }}
```
***
### BackInStockDeactivateNotify
Mit dieser Aktion wird eine bestehende Wiedervorrätig-Benachrichtigung deaktiviert.
**Anwendungsbeispiel**\
Nutzbar auf der Account-Übersichtsseite, auf der eingeloggte Kunden ihre aktiven Benachrichtigungen einsehen und entfernen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `productId` | Die ID des Produkts, für das die Benachrichtigung deaktiviert werden soll. |
| `email` | Die E-Mail-Adresse, für die die Benachrichtigung deaktiviert werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingProductId` | Parameter `productId` fehlt. |
| `missingEmail` | Parameter `email` fehlt. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsInventory](/frontend/referenz/module/wsinventory)
* [\$wsAccount.backInStockList](/frontend/referenz/module/wsAccount#\$wsaccount-backinstocklist)
**Beispiel** das zeigt, wie eine aktive Benachrichtigung über einen Button deaktiviert wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionBackInStockDeactivateNotify = $wsActions.create("BackInStockDeactivateNotify") }}
```
# Newsletter
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/newsletter
Newsletter-Aktionen für Abonnenten: Anmeldung, Double-Opt-In-Bestätigung und Abmeldung vom Newsletter direkt aus dem Frontend ausführen.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich Newsletter beschrieben. Mit diesen Aktionen können Kunden den Newsletter abonnieren, ihre Anmeldung bestätigen und sich wieder abmelden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `NewsletterSubscribe` | Meldet einen Kunden für den Newsletter an. |
| `NewsletterSubscribeConfirm` | Bestätigt die Newsletter-Anmeldung per Double-Opt-In. |
| `NewsletterUnsubscribe` | Meldet einen Kunden vom Newsletter ab. |
| `NewsletterUnsubscribeConfirm` | Bestätigt die Newsletter-Abmeldung per Double-Opt-In. |
***
## Aktionen
### NewsletterSubscribe
Mit dieser Aktion wird ein Kunde für den Newsletter angemeldet. Nach erfolgreicher Anmeldung erhält der Kunde eine Bestätigungs-E-Mail mit einem Double-Opt-In Link.
**Anwendungsbeispiel**\
Nutzbar auf einer Newsletter-Anmeldeseite, auf der Kunden ihre E-Mail-Adresse und optional eine oder mehrere Zielgruppen auswählen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `email` | Die E-Mail-Adresse, die für den Newsletter angemeldet werden soll. |
| `targetGroupId.(id)` | Optionale Zielgruppen-ID, für die der Kunde angemeldet werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingEmail` | Parameter `email` fehlt. |
| `emailCheckFailed` | Die angegebene E-Mail-Adresse ist ungültig. |
| `accountAlreadyExists` | Die E-Mail-Adresse ist bereits für den Newsletter angemeldet. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsNewsletter](/frontend/referenz/module/wsnewsletter)
* [\$wsNewsletter.getTargetGroups()](/frontend/referenz/module/wsnewsletter#\$wsnewsletter-gettargetgroups)
**Beispiel** das zeigt, wie ein Kunde seine E-Mail-Adresse und optional Zielgruppen auswählt, um den Newsletter zu abonnieren, inklusive Erfolgsausgabe nach der Anmeldung.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionNewsletterSubscribe = $wsActions.create("NewsletterSubscribe") }}
```
***
### NewsletterSubscribeConfirm
Mit dieser Aktion wird die Newsletter-Anmeldung per Double-Opt-In bestätigt. Der Kunde erhält nach der Anmeldung eine E-Mail mit einem Bestätigungslink, über den diese Aktion ausgelöst wird.
**Anwendungsbeispiel**\
Nutzbar auf der Bestätigungsseite, auf die der Kunde nach Klick auf den Opt-In-Link in der Anmelde-E-Mail weitergeleitet wird.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `unauthorized` | Es wurde kein gültiger Opt-In-Token übergeben. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsNewsletter](/frontend/referenz/module/wsnewsletter)
**Beispiel** das zeigt, wie nach erfolgreicher Bestätigung eine Erfolgsmeldung angezeigt wird und bei einem ungültigen Token ein Fehlerhinweis erscheint.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionNewsletterSubscribeConfirm = $wsActions.create('NewsletterSubscribeConfirm') }}
```
***
### NewsletterUnsubscribe
Mit dieser Aktion wird ein Kunde vom Newsletter abgemeldet. Der Kunde gibt dabei seine E-Mail-Adresse an und kann optional einzelne Zielgruppen abwählen.
**Anwendungsbeispiel**\
Nutzbar auf der Abmeldeseite, auf der Kunden ihre E-Mail-Adresse eingeben und sich von einzelnen oder allen Newsletter-Zielgruppen abmelden können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `email` | Die E-Mail-Adresse, die vom Newsletter abgemeldet werden soll. |
| `targetGroupId.(id)` | Optionale Zielgruppen-ID, von der der Kunde abgemeldet werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingEmail` | Parameter `email` fehlt. |
| `emailCheckFailed` | Die angegebene E-Mail-Adresse ist ungültig. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsNewsletter](/frontend/referenz/module/wsnewsletter)
* [\$wsNewsletter.getTargetGroups()](/frontend/referenz/module/wsnewsletter#\$wsnewsletter-gettargetgroups)
**Beispiel** das zeigt, wie ein Kunde seine E-Mail-Adresse eingibt und sich von einzelnen Zielgruppen abmeldet, inklusive Erfolgsausgabe.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionNewsletterUnsubscribe = $wsActions.create('NewsletterUnsubscribe') }}
```
***
### NewsletterUnsubscribeConfirm
Mit dieser Aktion wird die Newsletter-Abmeldung per Double-Opt-In bestätigt. Der Kunde erhält nach der Abmeldung eine E-Mail mit einem Bestätigungslink, über den diese Aktion ausgelöst wird.
**Anwendungsbeispiel**\
Nutzbar auf der Bestätigungsseite, auf die der Kunde nach Klick auf den Opt-In-Link in der Abmelde-E-Mail weitergeleitet wird.
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `unauthorized` | Es wurde kein gültiger Opt-In-Token übergeben. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsNewsletter](/frontend/referenz/module/wsnewsletter)
**Beispiel** das zeigt, wie nach erfolgreicher Bestätigung der Abmeldung eine Erfolgsmeldung angezeigt wird und bei einem ungültigen Token ein Fehlerhinweis erscheint.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionNewsletterUnsubscribeConfirm = $wsActions.create('NewsletterUnsubscribeConfirm') }}
```
# ProductRating
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/productrating
ProductRating-Aktionen für Produktbewertungen: Bewertungen durch eingeloggte Kunden erstellen, bearbeiten und wieder löschen lassen.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich Produktbewertungen beschrieben. Mit diesen Aktionen können Bewertungen erstellt, bearbeitet und gelöscht werden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `ProductRatingAdd` | Erstellt eine neue Produktbewertung. |
| `ProductRatingUpdate` | Bearbeitet eine bestehende Produktbewertung. |
| `ProductRatingDelete` | Löscht eine bestehende Produktbewertung. |
***
## Aktionen
### ProductRatingAdd
Mit dieser Aktion wird eine neue Bewertung für ein Produkt erstellt. Der Kunde muss dafür eingeloggt sein.
**Anwendungsbeispiel**\
Nutzbar auf der Produktdetailseite oder in der Bestellhistorie, um eingeloggten Kunden die Möglichkeit zu geben, ein gekauftes Produkt zu bewerten.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `productId` | Die ID des Produkts, das bewertet werden soll. |
| `orderId` | Die ID der Bestellung, zu der die Bewertung gehört. |
| `points` | Die Bewertung in Punkten (z.B. 1-5 Sterne). |
| `subject` | Der Titel der Bewertung. |
| `description` | Der Bewertungstext. |
| `anonymous` | Gibt an, ob die Bewertung anonym abgegeben werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `missingProductId` | Parameter `productId` fehlt. |
| `missingOrderId` | Parameter `orderId` fehlt. |
| `missingPoints` | Parameter `points` fehlt. |
| `ratingAlreadyExists` | Für dieses Produkt und diese Bestellung existiert bereits eine Bewertung. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsProductRating](/frontend/referenz/module/wsproductrating)
* [\$wsProductRating.checkRatingExistence()](/frontend/referenz/module/wsproductrating#\$wsproductrating-checkratingexistence)
* [\$wsProductRating.loadAllProductRatings()](/frontend/referenz/module/wsproductrating#\$wsproductrating-loadallproductratings)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#\$wsaccount-isloggedin)
**Beispiel** das zeigt, wie ein eingeloggter Kunde ein Produkt mit Sternebewertung, Titel und Kommentar bewerten kann, inklusive Erfolgsausgabe.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionProductRatingAdd = $wsActions.create("ProductRatingAdd") }}
```
***
### ProductRatingUpdate
Mit dieser Aktion wird eine bestehende Produktbewertung des eingeloggten Kunden bearbeitet.
**Anwendungsbeispiel**\
Nutzbar auf der Produktdetailseite oder im Kundenkonto, wenn ein Kunde seine abgegebene Bewertung nachträglich anpassen möchte.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `productId` | Die ID des Produkts, dessen Bewertung bearbeitet werden soll. |
| `orderId` | Die ID der Bestellung, zu der die Bewertung gehört. |
| `points` | Die neue Bewertung in Punkten. |
| `subject` | Der neue Titel der Bewertung. |
| `description` | Der neue Bewertungstext. |
| `anonymous` | Gibt an, ob die Bewertung anonym abgegeben werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `missingProductId` | Parameter `productId` fehlt. |
| `missingOrderId` | Parameter `orderId` fehlt. |
| `invalidRating` | Die Bewertung existiert nicht oder gehört nicht zu diesem Kundenkonto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsProductRating](/frontend/referenz/aktionen/productrating)
* [\$wsProductRating.loadSingleRating()](/frontend/referenz/module/wsproductrating#\$wsproductrating-loadsinglerating)
* [\$wsProductRating.loadRatingByAccount()](/frontend/referenz/module/wsproductrating#\$wsproductrating-loadratingbyaccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#\$wsaccount-isloggedin)
**Beispiel** das zeigt, wie ein Kunde eine bestehende Bewertung bearbeiten kann, mit vorausgefüllten Feldern.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionProductRatingUpdate = $wsActions.create("ProductRatingUpdate") }}
{{ var $myRating = $wsProductRating.loadSingleRating($myProduct, $myOrderId) }}
```
***
### ProductRatingDelete
Mit dieser Aktion wird eine bestehende Produktbewertung des eingeloggten Kunden gelöscht.
**Anwendungsbeispiel**\
Nutzbar auf der Produktdetailseite oder im Kundenkonto, wenn ein Kunde seine abgegebene Bewertung entfernen möchte.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `productId` | Die ID des Produkts, dessen Bewertung gelöscht werden soll. |
| `orderId` | Die ID der Bestellung, zu der die Bewertung gehört. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `missingProductId` | Parameter `productId` fehlt. |
| `missingOrderId` | Parameter `orderId` fehlt. |
| `invalidRating` | Die Bewertung existiert nicht oder gehört nicht zu diesem Kundenkonto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsProductRating](/frontend/referenz/aktionen/productrating)
* [\$wsProductRating.loadRatingByAccount()](/frontend/referenz/module/wsproductrating#\$wsproductrating-loadratingbyaccount)
* [\$wsAccount.isLoggedIn](/frontend/referenz/module/wsAccount#\$wsaccount-isloggedin)
**Beispiel** das zeigt, wie eine Bewertung über einen Button gelöscht wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionProductRatingDelete = $wsActions.create("ProductRatingDelete") }}
```
# Session
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/session
Session-Aktionen im Frontend: eigene Session-Variablen schreiben und nach fehlgeschlagenem Bezahlvorgang eine gesperrte Session entsperren.
In diesem Abschnitt werden die verfügbaren Aktionen der Session beschrieben. Mit diesen Aktionen können z.B. Session-Variablen geschrieben oder eine gesperrte Session nach einem fehlgeschlagenen Bezahlvorgang wieder entsperrt werden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `SessionUpdate` | Schreibt einen Wert in eine Session-Variable. |
| `SessionUnlock` | Entsperrt die Session nach einem fehlgeschlagenen Online-Bezahlvorgang. |
***
## Aktionen
### SessionUpdate
Mit dieser Aktion wird ein Wert in eine Session-Variable geschrieben. Die Variable wird dabei über den Parameternamen `session.(variableName)` adressiert, wobei `variableName` für den gewünschten Schlüssel innerhalb der Session steht.
**Anwendungsbeispiel**\
Nutzbar, um während des Nutzererlebnisses benutzerdefinierte Zustandsinformationen in der Session zu speichern, z.B. einen ausgewählten Filter, einen Fortschritt im Checkout oder einen temporären Hinweis, der seitenübergreifend verfügbar sein soll.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `session.(variableName)` | Der Schlüssel und Wert der Session-Variable, die gesetzt werden soll. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsSession](/frontend/referenz/module/wssession)
* [\$wsSession.set()](/frontend/referenz/module/wssession#\$wssession-set)
* [\$wsSession.get()](/frontend/referenz/module/wssession#\$wssession-get)
**Beispiel** das zeigt, wie ein Wert in eine Session-Variable geschrieben und anschließend ausgelesen wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionSessionUpdate = $wsActions.create("SessionUpdate") }}
{{ if $wsSession.get("lastViewedCategory") }}
Kategorie: {{= $wsSession.get("lastViewedCategory") }}
{{ /if }}
```
***
### SessionUnlock
Mit dieser Aktion wird eine gesperrte Session wieder entsperrt. Eine Session kann nach einem fehlgeschlagenen Online-Bezahlvorgang in einen gesperrten Zustand geraten, um unbeabsichtigte Folgeaktionen zu verhindern. `SessionUnlock` setzt diesen Sperrzustand zurück, sodass der Kunde den Vorgang erneut starten oder fortsetzen kann.
Diese Aktion erwartet keine Parameter und liefert keine Fehlerrückmeldungen.
**Anwendungsbeispiel**\
Nutzbar auf einer Fehler- oder Rücksprungs-Seite nach einem fehlgeschlagenen Zahlungsvorgang, um dem Kunden zu ermöglichen, die Zahlung erneut zu versuchen oder eine andere Zahlungsmethode auszuwählen.
**Zugehörige Module, Variablen & Methoden**
* [\$wsSession](/frontend/referenz/module/wssession)
* [\$wsSession.isLocked](/frontend/referenz/module/wssession#\$wssession-islocked)
**Beispiel** das zeigt, wie einem Kunden bei gesperrter Session die Möglichkeit gegeben wird, diese über einen Button zu entsperren.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsSession.isLocked }}
{{ var $myActionSessionUnlock = $wsActions.create("SessionUnlock") }}
{{ /if }}
```
# Stores
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/stores
Stores-Aktionen für Märkte und Filialen: Markt für aktuelle Session oder den Checkout-Prozess setzen, ändern und für Click & Collect nutzen.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich Märkte (Stores) beschrieben. Mit diesen Aktionen kann z.B. ein Markt für die aktuelle Session oder den Checkout-Prozess ausgewählt werden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `SelectStore` | Setzt einen Markt als aktiven Markt für die aktuelle Session. |
***
## Aktionen
### SelectStore
Mit dieser Aktion wählt der Kunde einen Markt als seinen aktiven Markt für die aktuelle Session aus. Die Auswahl wird sofort übernommen und steht anschließend z.B. für die Anzeige von standortbezogenen Inhalten oder als Vorauswahl im Checkout zur Verfügung.
**Anwendungsbeispiel**\
Nutzbar, um z.B. auf einer Markt-Übersichtsseite, auf der dem Kunden alle verfügbaren Märkte angezeigt werden und er per Klick seinen gewünschten Markt auswählen kann, z.B. um Öffnungszeiten, Verfügbarkeiten oder Click & Collect-Optionen für seinen Markt zu sehen.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `storeId` | Die ID des Marktes, der als aktiver Markt gesetzt werden soll. |
**Fehlercodes**
| **Code** | **Beschreibung** |
| - | - |
| `missingStoreId` | Parameter `storeId` fehlt. |
| `invalidStoreId` | Die angegebene Markt-ID existiert nicht oder ist ungültig. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsStores](/frontend/referenz/module/wsstores)
* [\$wsStores.loadAllStores()](/frontend/referenz/module/wsstores#\$wsstores-loadallstores)
* [\$wsStores.selectedStore](/frontend/referenz/module/wsstores#\$wsstores-selectedstore)
**Beispiel** das zeigt, wie alle verfügbaren Märkte als Auswahlliste dargestellt werden und der aktuell ausgewählte Markt vorausgewählt ist.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionSelectStore = $wsActions.create("SelectStore") }}
```
# TestMode
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/testmode
TestMode-Aktionen: Testmodus im Frontend aktivieren, deaktivieren und zwischen Test- und Live-Modus wechseln, ohne Live-Betrieb zu beeinflussen.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich Testmodus beschrieben. Mithilfe dieser Aktionen können Sie den Testmodus aktivieren und deaktivieren. Beim Aktivieren sowie im aktiven Testmodus können Sie außerdem das erweiterte Debugging einschalten, fehlgeschlagene Zahlungen simulieren und der Storefront signalisieren, dass sie die Test-API der WEBSALE-Suche verwenden soll. Zudem können Sie die Views bei jedem Request aus den Template-Quellen kompilieren lassen.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `TestModeOn` | Aktiviert den Testmodus, optional mit Debugging, simulierten fehlgeschlagenen Zahlungen, dem Signal für die Test-API der WEBSALE Suche und dem Kompilieren der Views bei jedem Request. |
| `TestModeOff` | Deaktiviert den Testmodus. |
| `TestModeChange` | Ändert die Schalter des aktiven Testmodus, ohne ihn zu verlassen. |
***
## Aktionen
### TestModeOn
Mit dieser Aktion wird der Testmodus aktiviert. Der Benutzer muss dafür das konfigurierte Testmodus-Passwort angeben.
Mit dem Parameter `makePaymentFail` werden Zahlungen im Testmodus zusätzlich als fehlgeschlagen simuliert. Dadurch laufen Bestellungen gezielt in den Fehlerfall, sodass die dafür vorgesehenen Templates und Abläufe geprüft werden können. Die aktuelle Konfiguration kann im Template über [\$wsTestMode](/frontend/referenz/module/wstestmode) abgefragt werden.
Mit dem Parameter `searchTestApi` signalisieren Sie der Storefront, dass sie statt der produktiven API die Test-API der WEBSALE-Suche verwenden soll. Am Shop selbst verändert der Schalter nichts. Dieser ruft die WEBSALE-Suche nicht selbst auf, sondern reicht den Wert über [\$wsTestMode.searchTestApi](/frontend/referenz/module/wstestmode#\$wstestmode-searchtestapi) weiter.
Mit dem Parameter `compileTemplates` kompiliert der Shop die Views bei jedem Request aus den Template-Quellen, statt sie aus dem vorkompilierten Theme zu laden. Dadurch sind Änderungen an den Templates sofort sichtbar. Aufgrund der damit verbundenen Zeitkosten eignet sich diese Einstellung nur für Tests. Die aktuelle Konfiguration lässt sich über [\$wsTestMode.compileTemplates](/frontend/referenz/module/wstestmode#\$wstestmode-compiletemplates) abfragen.
Schalter, die im Formular nicht angehakt sind, sind nach dem Aktivieren aus.
**Anwendungsbeispiel**\
Nutzbar auf der Testmodus Seite (`testMode.htm`), über die Shopbetreiber oder Tester den Testmodus mit einem Passwort aktivieren können, um testspezifische Inhalte zu sehen.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `password` | Das Passwort zur Aktivierung des Testmodus. |
| `debug` | Aktiviert das erweiterte Debugging (Wert: “`on`”). |
| `makePaymentFail` | Simuliert Zahlungen im Testmodus als fehlgeschlagen (Wert: “`on`”). |
| `searchTestApi` | Signalisiert der Storefront, dass sie die Test-API der WEBSALE Suche verwenden soll (Wert: “`on`”). |
| `compileTemplates` | Kompiliert die Views bei jedem Request aus den Template-Quellen statt aus dem vorkompilierten Theme (Wert: “`on`”). |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `noPassword` | Parameter `password` fehlt oder ist leer. |
| `invalidPassword` | Das angegebene Passwort ist falsch. |
| `tooManyAttempts` | Der Zugang zum Testmodus ist für die IP-Adresse des Aufrufers wegen zu vieler fehlgeschlagener Passworteingaben vorübergehend gesperrt (sofern die Sperre über `ipBlockEnabled` aktiviert ist). Grenzwerte und Sperrdauer legen Sie unter [general.testMode](/konfiguration/general-allgemeine-shopeinstellungen#general-testmode-testmodus) fest. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsTestMode](/frontend/referenz/module/wstestmode)
* [\$wsTestMode.active](/frontend/referenz/module/wstestmode#\$wstestmode-active)
* [\$wsTestMode.debug](/frontend/referenz/module/wstestmode#\$wstestmode-debug)
* [\$wsTestMode.makePaymentFail](/frontend/referenz/module/wstestmode#\$wstestmode-makepaymentfail)
* [\$wsTestMode.searchTestApi](/frontend/referenz/module/wstestmode#\$wstestmode-searchtestapi)
* [\$wsTestMode.compileTemplates](/frontend/referenz/module/wstestmode#\$wstestmode-compiletemplates)
**Beispiel** das zeigt, wie der Testmodus über ein Passwortformular aktiviert wird. Optional sind Debugging, simulierte fehlgeschlagene Zahlungen und das Signal für die Test-API der WEBSALE-Suche.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $cActionTestModeOn = $wsActions.create("TestModeOn") }}
```
***
### TestModeOff
Mit dieser Aktion wird der Testmodus deaktiviert und der Shop kehrt in den normalen Live-Betrieb zurück.
**Anwendungsbeispiel**\
Nutzbar auf der Testmodus-Seite oder im Shop-Header, um den Testmodus direkt im Shop zu deaktivieren.
**Zugehörige Module, Variablen & Methoden**
* [\$wsTestMode](/frontend/referenz/module/wstestmode)
* [\$wsTestMode.active](/frontend/referenz/module/wstestmode#\$wstestmode-active)
**Beispiel** das zeigt, wie der Testmodus über einen Button deaktiviert wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionTestModeOff = $wsActions.create("TestModeOff") }}
```
***
### TestModeChange
Mit dieser Aktion können Sie die Schalter des aktiven Testmodus ändern, ohne den Testmodus zu verlassen. Voraussetzung dafür ist, dass der Testmodus zuvor mit dem Passwort aktiviert wurde.
Die Aktion setzt beim Speichern über das Formular immer alle Schalter. Eine nicht angehakte Checkbox schickt der Browser gar nicht erst mit. Ein Schalter, der im Formular fehlt oder nicht angehakt ist, ist nach dem Speichern also aus. Bilden Sie deshalb alle Schalter im Formular ab. Über die [Storefront API](/schnittstellen/storefront-api/storefront-api-testmodus#post-testmodeupdate) gilt das nicht. Dort ändert `testMode/update` nur die mitgesendeten Schalter.
**Anwendungsbeispiel**\
Nutzbar auf der Testmodus-Seite, um im aktiven Testmodus beispielsweise das Debugging auszuschalten, ohne den Testmodus zu beenden.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `debug` | Aktiviert das erweiterte Debugging (Wert: “`on`”). Fehlt der Parameter, wird das Debugging ausgeschaltet. |
| `makePaymentFail` | Simuliert Zahlungen im Testmodus als fehlgeschlagen (Wert: “`on`”). Fehlt der Parameter, wird die Simulation ausgeschaltet. |
| `searchTestApi` | Signalisiert der Storefront, dass sie die Test-API der WEBSALE Suche verwenden soll (Wert: “`on`”). Fehlt der Parameter, wird der Schalter ausgeschaltet. |
| `compileTemplates` | Kompiliert die Views bei jedem Request aus den Template-Quellen statt aus dem vorkompilierten Theme (Wert: “`on`”). Fehlt der Parameter, wird der Schalter ausgeschaltet. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notAllowed` | Der Testmodus ist für die Session nicht aktiv. Aktivieren Sie ihn zuerst über [TestModeOn](#testmodeon). |
**Zugehörige Module, Variablen & Methoden**
* [\$wsTestMode](/frontend/referenz/module/wstestmode)
* [\$wsTestMode.active](/frontend/referenz/module/wstestmode#\$wstestmode-active)
* [\$wsTestMode.debug](/frontend/referenz/module/wstestmode#\$wstestmode-debug)
* [\$wsTestMode.makePaymentFail](/frontend/referenz/module/wstestmode#\$wstestmode-makepaymentfail)
* [\$wsTestMode.searchTestApi](/frontend/referenz/module/wstestmode#\$wstestmode-searchtestapi)
* [\$wsTestMode.compileTemplates](/frontend/referenz/module/wstestmode#\$wstestmode-compiletemplates)
**Beispiel** das zeigt, wie die Schalter des aktiven Testmodus geändert werden.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionTestModeChange = $wsActions.create("TestModeChange") }}
```
# Voucher
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/voucher
Voucher-Aktionen im Warenkorb: Gutscheincodes mit VoucherAdd einlösen und über VoucherDelete wieder aus dem aktuellen Warenkorb entfernen.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich Gutscheine beschrieben. Mit diesen Aktionen können Gutscheincodes im Warenkorb eingelöst und wieder entfernt werden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `VoucherAdd` | Löst einen Gutscheincode im Warenkorb ein. |
| `VoucherDelete` | Entfernt einen eingelösten Gutschein aus dem Warenkorb. |
***
## Aktionen
### VoucherAdd
Mit dieser Aktion wird ein Gutscheincode im Warenkorb eingelöst.
**Anwendungsbeispiel**\
Nutzbar auf der Warenkorbseite oder im Warenkorb-Offcanvas, wo Kunden einen Gutscheincode eingeben und direkt auf ihre Bestellung anwenden können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `id` | Der Gutscheincode, der eingelöst werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingId` | Parameter `id` fehlt. |
| `invalidVoucher` | Der angegebene Gutscheincode ist ungültig oder bereits eingelöst. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsVoucher](/frontend/referenz/module/wsvoucher)
* [\$wsVoucher.vouchers](/frontend/referenz/module/wsvoucher#\$wsvoucher-vouchers)
* [\$wsVoucher.totalValue](/frontend/referenz/module/wsvoucher#\$wsvoucher-totalvalue)
**Beispiel** das zeigt, wie ein Gutscheincode über ein Eingabefeld eingelöst wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionVoucherAdd = $wsActions.create("VoucherAdd") }}
```
***
### VoucherDelete
Mit dieser Aktion wird ein bereits eingelöster Gutschein aus dem Warenkorb entfernt.
**Anwendungsbeispiel**\
Nutzbar auf der Warenkorbseite oder im Warenkorb-Offcanvas, wenn Kunden einen eingelösten Gutschein wieder entfernen möchten.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `id` | Die ID des Gutscheins, der entfernt werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingId` | Parameter `id` fehlt. |
| `invalidVoucherId` | Der angegebene Gutschein existiert nicht oder gehört nicht zu diesem Warenkorb. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsVoucher](/frontend/referenz/module/wsvoucher)
* [\$wsVoucher.vouchers](/frontend/referenz/module/wsvoucher#\$wsvoucher-vouchers)
* [\$wsVoucher.totalValue](/frontend/referenz/module/wsvoucher#\$wsvoucher-totalvalue)
**Beispiel** das zeigt, wie alle eingelösten Gutscheine aufgelistet werden und jeder einzelne über einen Button entfernt werden kann.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ foreach $myVoucher in $wsVoucher.vouchers }}
{{ var $myActionVoucherDelete = $wsActions.create("VoucherDelete") }}
{{ /foreach }}
```
# WatchList
Source: https://dokumentation.websale.de/frontend/referenz/aktionen/watchlist
WatchList-Aktionen für die Merkliste: Produkte über WatchListItemAdd hinzufügen und über WatchListItemDelete aus der Wunschliste entfernen.
In diesem Abschnitt werden die verfügbaren Aktionen im Bereich Merkliste beschrieben. Mit diesen Aktionen können Produkte zur Merkliste hinzugefügt oder daraus entfernt werden.
***
## Aktionen im Überblick
| **Aktion** | **Beschreibung** |
| - | - |
| `WatchListItemAdd` | Fügt ein oder mehrere Produkte zur Merkliste hinzu. |
| `WatchListItemDelete` | Entfernt ein Produkt aus der Merkliste. |
| `AddWatchList` | Erstellt eine neue Merkliste. |
| `DeleteWatchList` | Löscht eine bestehende Merkliste. |
| `RenameWatchList` | Benennt eine bestehende Merkliste um. |
***
## Aktionen
### WatchListItemAdd
Mit dieser Aktion wird ein Produkt zur Merkliste des Benutzers hinzugefügt. Es können sowohl einzelne Produkte als auch mehrere Produkte gleichzeitig übergeben werden.
**Anwendungsbeispiel**\
Nutzbar auf Produkt- oder Kategorieseiten, auf denen Kunden Artikel auf ihre Merkliste setzen können, um sie später wiederzufinden oder zu kaufen.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `productId` | Die ID des Produkts, das zur Merkliste hinzugefügt werden soll. |
| `freeFields.` | Optionale Freifelder, die dem Merklisten-Eintrag zugeordnet werden können. |
| `multiProducts..` | Ermöglicht das gleichzeitige Hinzufügen mehrerer Produkte mit jeweiliger Menge. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingProductId` | Parameter `productId` fehlt oder ist leer. |
| `invalidProductId` | Das Produkt mit der angegebenen `productId` existiert nicht. |
| `invalidVariantId` | Die angegebene Variante des Produkts ist ungültig oder nicht vorhanden. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsWatchList](/frontend/referenz/module/wswatchlist)
* [\$wsWatchList.watchLists](/frontend/referenz/module/wswatchlist#\$wswatchlist-watchlists)
* [\$wsWatchList.loadWatchList()](/frontend/referenz/module/wswatchlist#\$wswatchlist-loadwatchlist)
* [\$wsWatchList.isProductOnWatchList()](/frontend/referenz/module/wswatchlist#\$wswatchlist-isproductonwatchlist)
* [\$wsWatchList.countWatchListsWithProduct()](/frontend/referenz/module/wswatchlist#\$wswatchlist-countwatchlistswithproduct)
**Beispiel** das zeigt, wie ein Produkt zur Standard-Merkliste hinzugefügt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionWatchListItemAdd = $wsActions.create("WatchListItemAdd") }}
```
***
### WatchListItemDelete
Mit dieser Aktion wird ein Eintrag aus der Merkliste des Benutzers entfernt.
**Anwendungsbeispiel**\
Nutzbar auf der Merklisten-Seite, auf der Kunden einzelne Produkte wieder von ihrer Merkliste löschen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `watchListItemId` | Die ID des Merklisten-Eintrags, der gelöscht werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `missingWatchListItemId` | Parameter `watchListItemId` fehlt oder ist leer. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsWatchList](/frontend/referenz/module/wswatchlist)
* [\$wsWatchList.watchLists](/frontend/referenz/module/wswatchlist#\$wswatchlist-watchlists)
* [\$wsWatchList.loadWatchList()](/frontend/referenz/module/wswatchlist#\$wswatchlist-loadwatchlist)
* [\$wsWatchList.loadWatchListItemId()](/frontend/referenz/module/wswatchlist#\$wswatchlist-loadwatchlistitemid)
**Beispiel** das zeigt, wie ein Produkt anhand seiner Merklisten-Eintrags-ID aus der Standard-Merkliste entfernt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionWatchListItemDelete = $wsActions.create("WatchListItemDelete") }}
{{ var $myWatchListItemId = $wsWatchList.loadWatchListItemId("default", $myProduct.id) }}
```
***
### AddWatchList
Mit dieser Aktion wird eine neue Merkliste für den eingeloggten Benutzer erstellt.
**Anwendungsbeispiel**\
Nutzbar auf der Merklisten-Verwaltungsseite, auf der Kunden zusätzlich Merklisten anlegen können, z.B. für verschiedene Anlässe oder Kategorien.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `watchListName` | Der Name der neuen Merkliste. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `missingWatchListName` | Parameter `watchListName` fehlt. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsWatchList](/frontend/referenz/module/wswatchlist)
* [\$wsWatchList.watchLists](/frontend/referenz/module/wswatchlist#\$wswatchlist-watchlists)
**Beispiel** das zeigt, wie eine neue Merkliste über ein Eingabefeld erstellt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionAddWatchList = $wsActions.create("AddWatchList") }}
```
***
### DeleteWatchList
Mit dieser Aktion wird eine bestehende Merkliste des eingeloggten Benutzers gelöscht.
**Anwendungsbeispiel**\
Nutzbar auf der Merklisten-Verwaltungsseite, auf der Kunden nicht mehr benötigte Merklisten entfernen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `watchListId` | Die ID der Merkliste, die gelöscht werden soll. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `missingWatchListId` | Parameter `watchListId` fehlt. |
| `invalidWatchListId` | Die angegebene Merkliste existiert nicht oder gehört nicht zu diesem Benutzerkonto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsWatchList](/frontend/referenz/module/wswatchlist)
* [\$wsWatchList.watchLists](/frontend/referenz/module/wswatchlist#\$wswatchlist-watchlists)
**Beispiel** das zeigt, wie eine Merkliste über einen Button gelöscht wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionDeleteWatchList = $wsActions.create("DeleteWatchList") }}
```
***
### RenameWatchList
Mit dieser Aktion wird eine bestehende Merkliste des eingeloggten Benutzers umbenannt.
**Anwendungsbeispiel**\
Nutzbar auf der Merklisten-Verwaltungsseite, auf der Kunden den Namen einer bestehenden Merkliste anpassen können.
**Parameter**
| **Name** | **Beschreibung** |
| - | - |
| `watchListId` | Die ID der Merkliste, die umbenannt werden soll. |
| `watchListName` | Der neue Name der Merkliste. |
**Fehlercodes**
| **Fehlercode** | **Beschreibung** |
| - | - |
| `notLoggedIn` | Der Benutzer ist nicht eingeloggt. |
| `missingWatchListId` | Parameter `watchListId` fehlt. |
| `missingWatchListName` | Parameter `watchListName` fehlt. |
| `invalidWatchListId` | Die angegebene Merkliste existiert nicht oder gehört nicht zu diesem Benutzerkonto. |
**Zugehörige Module, Variablen & Methoden**
* [\$wsWatchList](/frontend/referenz/module/wswatchlist)
* [\$wsWatchList.watchLists](/frontend/referenz/module/wswatchlist#\$wswatchlist-watchlists)
**Beispiel** das zeigt, wie eine Merkliste über ein Eingabefeld umbenannt wird.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myActionRenameWatchList = $wsActions.create("RenameWatchList") }}
```
# Anweisungen und Ausgabe
Source: https://dokumentation.websale.de/frontend/referenz/anweisungen
Anweisungen und Ausgabe in Templates: Syntax für Verarbeitung, Ausgabe und automatisches Escaping verstehen und kontextsicher einsetzen.
Beim Erstellen von Templates reicht es nicht aus, nur [Variablen](/frontend/referenz/variablen), [Funktionen ](/frontend/referenz/funktionen)oder [Operatoren ](/frontend/referenz/operatoren)zu kennen. Ebenso wichtig ist es, wie ein Ausdruck im Template verarbeitet wird. Die verwendete Syntax entscheidet darüber, ob eine Anweisung nur ausgeführt, ein Wert ausgegeben oder eine Ausgabe automatisch escaped wird.
Diese Unterscheidung ist für die Template-Entwicklung relevant, weil sie direkten Einfluss auf das erzeugte Ergebnis hat. Je nach Schreibweise erscheint ein Wert im HTML, wird nur intern verarbeitet oder unverändert ausgegeben. Dadurch bestimmt die Syntax nicht nur die Ausgabe selbst, sondern auch, ob Inhalte für den jeweiligen Kontext korrekt und sicher ausgegeben werden.
Die verschiedenen Formen von Anweisungen helfen daher dabei, Template-Logik und Ausgabe sauber zu steuern. Sie legen fest, wann ein Ausdruck lediglich verarbeitet wird und wann sein Ergebnis im generierten Dokument erscheint. Gleichzeitig steuern sie das Escaping und damit den Umgang mit Sonderzeichen, HTML-Inhalten oder anderen Ausgabekontexten.
Diese Seite beschreibt die verfügbaren Schreibweisen für Anweisungen und zeigt, wie sie sich auf Verarbeitung, Ausgabe und Escaping auswirken.
***
## Anweisungen im Überblick
| **Syntax** | **Beschreibung** | Typische Verwendung |
| - | - | - |
| `{{ ... }}` | Führt eine Anweisung aus, ohne eine Ausgabe zu erzeugen. | Variablen setzen, Hilfslogik ausführen. |
| `{{= … }}` | Gibt einen Wert aus und ersetzt dabei HTML-Sonderzeichen. | Normale Ausgabe im HTML. |
| `{{! … !}}` | Gibt einen Wert aus, ohne HTML-Sonderzeichen zu ersetzen. | Bereits aufbereitete Inhalte gezielt unverändert
ausgeben. |
| `{{ autoescape “js” }} … `
`{{ /autoescape }}` | Wechselt den Escaping-Modus innerhalb eines Blocks. | Ausgabe in speziellen Kontexten, z.B. JavaScript |
## Anweisungen ohne Ausgabe
Mit `{{ ... }}` wird eine Anweisung ausgeführt, ohne dass ihr Ergebnis direkt ausgegeben wird. Diese Schreibweise wird verwendet, wenn im Template etwas vorbereitet oder verarbeitet werden soll, ohne dass an dieser Stelle bereits Inhalt im generierten Dokument bzw. Seite erscheint.
Typische Anwendungsfälle sind das Setzen von Variablen, das Vorbereiten von Hilfswerten oder das Aufrufen von Logik, deren Ergebnis erst später benötigt wird.
### **Beispiel**
In diesem Beispiel wird der Produktname in einer Variablen gespeichert. An dieser Stelle wird jedoch noch nichts ausgegeben.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myVariableForProductname = $product.name }}
```
### Verwendung
Diese Syntax ist sinnvoll, wenn ein Wert zunächst nur weiterverarbeitet oder für eine spätere Ausgabe vorbereitet werden soll.
Sie sollte verwendet werden, wenn:
* eine Variable gesetzt wird
* ein Wert zwischengespeichert wird
* eine Anweisung nur der Template-Logik dient
* an dieser Stelle keine direkte Ausgabe im HTML gewünscht ist
***
## Ausgabe mit Escaping
Mit `{{= … }}` wird ein Wert ausgegeben und dabei automatisch escaped. Diese Schreibweise ist der Standard für die Ausgabe im Template, wenn Inhalte im HTML erscheinen sollen.
Einfache `(')` und doppelte `(")` Anführungszeichen innerhalb von `{{= … }}` sind gleichwertig. Der Unterschied wirkt sich nur auf das Syntax-Highlighting im Code-Editor aus.
Escaping sorgt dafür, dass Sonderzeichen nicht als HTML interpretiert werden. Dadurch bleibt die Ausgabe korrekt und Inhalte werden als Text behandelt.
### Beispiel
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= $product.name }}
```
Enthält `$product.name` beispielsweise den Wert
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Tom & Jerry
```
wird daraus in der HTML-Ausgabe
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<b>Tom & Jerry</b>
```
Die Zeichen werden also so ausgegeben, dass sie im Browser korrekt dargestellt werden und nicht als HTML-Markup interpretiert werden.
### Verwendung
Diese Syntax sollte für normale Ausgaben im Template grundsätzlich bevorzugt werden.
Sie sollte verwendet werden, wenn:
* Text im HTML ausgegeben werden soll
* Inhalte aus Variablen ausgegeben werden
* nicht ausdrücklich gewünscht ist, dass HTML unverändert übernommen wird
* eine sichere Standardausgabe benötigt wird
In der Praxis ist `{{= … }}` in den meisten Fällen die richtige Wahl.
***
## Escaping für einen Bereich festlegen
Mit `autoescape` kann für einen zusammenhängenden Bereich festgelegt werden, wie Ausgaben escaped werden sollen. Das ist vor allem dann relevant, wenn Inhalte nicht im normalen HTML-Kontext ausgegeben werden, sondern beispielsweise innerhalb von JavaScript.
### Beispiel
```javascript theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ autoescape "js" }}
const productName = "{{= $product.name }}";
{{ /autoescape }}
```
In diesem Beispiel wird der Escaping-Modus für JavaScript gesetzt. Dadurch werden Ausgaben innerhalb dieses Bereichs passend für diesen Kontext behandelt.
Enthält `$product.name` zum Beispiel den Wert `Damen-Jacke "Alpine"` , wird daraus `"Damen-Jacke \"Alpine\"` , sodass die Anführungszeichen den JavaScript-String nicht unterbrechen.
### Verwendung
Diese Syntax sollte verwendet werden, wenn die Ausgabe in einem speziellen Ausgabekontext erfolgt, für den ein anderer Escaping-Modus erforderlich ist.
Das ist insbesondere sinnvoll, wenn Inhalte innerhalb von JavaScript, JSON oder vergleichbaren Kontexten ausgegeben werden.
***
## Ausgabe ohne Escaping
Mit `{{! … !}}` wird ein Wert unverändert ausgegeben. Es erfolgt kein automatisches Escaping. Die Ausgabe wird also genau so in das generierte Dokument übernommen, wie der Wert vorliegt.
Das ist nur dann sinnvoll, wenn der Inhalt bewusst ungeescaped ausgegeben werden soll, etwa weil er bereits korrekt als HTML formatiert wurde.
### Beispiel
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{! $product.name !}}
```
Enthält `$product.name` beispielsweise den Wert
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Tom & Jerry
```
wird dieser Inhalt in der HTML-Ausgabe auch als HTML übernommen
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Tom & Jerry
```
### Verwendung
Diese Syntax sollte nur gezielt und mit Vorsicht verwendet werden.
Sie sollte verwendet werden, wenn:
* Inhalte bewusst als HTML ausgegeben werden sollen
* der auszugebende Wert bereits korrekt aufbereitet ist
* kein zusätzliches Escaping mehr erfolgen darf
Sie sollte nicht verwendet werden, wenn gewöhnlicher Text ausgegeben werden soll. In solchen Fällen ist `{{= … }}` die richtige Wahl.
# Blöcke
Source: https://dokumentation.websale.de/frontend/referenz/blocke
Blöcke als Grundstruktur von Templates: Header, Footer und Navigation in benannte Bereiche teilen und unabhängig erweitern oder überschreiben.
Blöcke bilden die grundlegende Struktur eines [Templates](/frontend/die-basics/template-theme) und ermöglichen eine flexible Anpassung der Storefront. Sie unterteilen das Layout in klar benannte, isolierte Bereiche wie Header, Footer oder Navigation, die unabhängig voneinander angepasst werden können.
Diese Seite behandelt alles, was es über Blöcke im Detail zu wissen gibt: was sie können, was sie nicht können und wie man sie sinnvoll einsetzt.
## Grundprinzip
Blöcke bauen auf dem Zusammenspiel von Basis- und View-Templates auf. Das [Basis-Template](/frontend/die-basics/template-theme#2-basis-template-layout-template) definiert das übergeordnete Seitenlayout mit allem, was auf jeder Seite gleich bleibt - wie Header, Footer, Navigation oder eingebundene Skripte. Das [View-Template](/frontend/die-basics/template-theme#4-view-templates-seiten-templates) ist das Template einer konkreten Seite - es bindet das Basis Template per `{{ extends }}` ein und befüllt einzelne Bereiche mit seitenspezifischem Inhalt.
Ein Block ist ein benannter Bereich innerhalb eines Templates, der durch `{{ block “name” }}` geöffnet und durch `{{ /block }}` geschlossen wird. Er ist sowohl ein Struktur- als auch ein Inhaltsbaustein. Im Basis-Template legt er fest, welche Bereiche eine Seite hat und wo sie sich befinden, inklusive eines Standardinhalts, der angezeigt wird, solange ein View-Template diesen Block nicht explizit überschreibt. Im View-Template füllt er genau diese Bereiche mit seitenspezifischem Inhalt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ block "header" }}
Standard-Header
{{ /block }}
```
***
## Blöcke überschreiben
Ein View-Template greift einen Block auf, indem es ihn mit demselben Namen erneut definiert. Dabei gibt es drei Möglichkeiten:
1. Der Standardinhalt wird vollständig ersetzt:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ extends "layouts/default.htm" }}
{{ block "header" }}
Willkommen im Shop!
{{ /block }}
```
2. Mit `append` - der neue Inhalt wird hinter dem Standardinhalt eingefügt:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ block "header" append }}
Versandkostenfreiheit ab 50 €
{{ /block }}
```
3. Mit `prepend` - der neue Inhalt wird vor dem Standardinhalt eingefügt:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ block "header" prepend }}
Kostenloser Versand heute!
{{ /block }}
```
Der Basis-Block bleibt in allen Fällen unverändert. `append` und `prepend`sind praktisch, wenn der Standardinhalt eines Blocks grundsätzlich passt, aber auf einzelnen Seiten um zusätzliche Inhalte ergänzt werden soll.
***
## Verwendung von Blöcken in Templates
Blöcke können nicht in jedem Template-Typ definiert oder überschrieben werden. Es kommt darauf an, welche Rolle ein Template im System übernimmt:
* **Basis-Templates** (Layout-Templates) sind der einzige Ort, an dem Blöcke definiert werden. Sie legen fest, welche Bereiche einer Seite existieren und welche Standardinhalte diese haben.
* **View-Templates** (Seiten-Templates) und **E-Mail-Templates** können Blöcke eines Basis-Templates überschreiben oder erweitern. Beide binden ein Basis-Template per `{{ extends }}` ein. Dabei gilt eine wichtige Einschränkung: Ein Template mit `{{ extends }}` darf ausschließlich aus Blockanweisungen bestehen. Kein HTML, kein Code, kein Include darf außerhalb eines Blocks stehen.
Typische Blöcke, die das Standard-Layout bereitstellt:
| **Block** | **Typischer Inhalt** |
| - | - |
| `header` | Kopfbereich der Seite |
| `content_main` | Hauptinhalt der Seite |
| `footer` | Fußbereich der Seite |
| `scripts` | JavaScript am Seitenende |
***
## Blöcke und andere Konstrukte
Im Template-System gibt es mehrere Möglichkeiten, Code zu strukturieren und wiederzuverwenden. Blöcke sind dabei nur eines von mehreren Werkzeugen.
Blöcke reservieren benannte Platzhalter im Layout, die ein View-Template später mit seitenspezifischem Inhalt füllen kann. Sie funktionieren von oben nach unten - das Basis-Template gibt den Rahmen vor, das View-Template füllt ihn. Blöcke sind das Bindeglied zwischen Layout und Seiteninhalt.
[Includes](/frontend/die-basics/template-theme#5-components-includes) binden eine separate Template-Datei an einer bestimmten Stelle ein - ähnlich wie ein Baustein, der an mehreren Stellen eingesetzt werden kann. Ein Breadcrumb oder eine Fehlermeldung sind typische Beispiele - der Code wird einmal geschrieben und überall dort eingebunden, wo er gebraucht wird. Anders als Blöcke können Includes Variablen entgegennehmen und sind damit flexibel in ihren Parametern.
[Module](/frontend/referenz/module) wie `$wsBasket` oder `$wsProducts` stellen Daten bereit. Sie sind keine Template-Bausteine sondern serverseitige Datenquellen, auf die man im Template zugreift.
In der Praxis greifen alle drei ineinander. Ein Block definiert den Bereich der Seite, innerhalb des Blocks werden Includes eingebunden - diese greifen über Module auf die benötigten Daten zu.
***
## Erlaubter Inhalt
### HTML und Template-Syntax
Innerhalb eines Blocks sind erlaubt:
* Beliebiges HTML
* Variablendeklarationen (`{{ var ... }}`) und Ausgaben (`{{= ... }}`)
* Kontrollstrukturen wie `{{ if }}`, `{{ foreach }}`, `{{ switch }}`
* Includes (`{{ include ... }}`)
* Modulzugriffe (`$wsBasket.items`, `$wsCheckout.sum.total` etc.)
### JavaScript und CSS
Blöcke wie `head` oder `scripts` können ohne Einschränkungen `
{{ /if }}
{{ /block }}
```
### Block, der einen anderen Block enthält
Im Basis-Template können Blöcke ineinander verschachtelt werden. Jeder innere Block (hier `sidebar` und `main`) ist dabei unabhängig überschreibbar.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{# Basis-Template #}}
{{ block "content" }}
{{ block "sidebar" }}
{{ /block }}
{{ block "main" }}
Standard-Inhalt
{{ /block }}
{{ /block }}
```
### Negativbeispiel
Ein View-Template, das `{{ extends }}` verwendet, darf ausschließlich aus Blockanweisungen bestehen. Code oder HTML außerhalb eines Blocks ist ungültig und führt zu Fehlern.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{# Ungültig – Code außerhalb eines Blocks #}}
{{ extends "layouts/default.htm" }}
Dieser Text steht außerhalb eines Blocks – das funktioniert nicht.
{{ block "content_main" }}
Das hier ist korrekt.
{{ /block }}
```
# Components
Source: https://dokumentation.websale.de/frontend/referenz/components
Components der WEBSALE Template-Sprache: wiederverwendbare Bausteine für strukturierte, modulare Frontend-Komponenten im Shop-Template.
# Conditions
Source: https://dokumentation.websale.de/frontend/referenz/conditions
Conditions in der WEBSALE Template-Sprache: Bedingungen formulieren und Ausgaben oder Template-Logik abhängig von Werten und Status steuern.
# Datentypen
Source: https://dokumentation.websale.de/frontend/referenz/datentypen
Basisdatentypen der WEBSALE Template-Sprache: String, Zahl, Bool, Listen und Maps korrekt notieren und im Template sicher verarbeiten.
Man unterscheidet folgende Basisdatentypen:
## String
Ein String ist eine Zeichenkette, d. h. eine Folge von Zeichen (z. B. Buchstaben, Ziffern, Sonderzeichen und Steuerzeichen). Strings müssen immer zwischen zwei Hochkommas oder Anführungszeichen notiert werden.
| | |
| - | - |
| `"Wert1, Wert2, Wert3, Wert4"` | String |
| `'Wert1, Wert2, Wert3, Wert4'` | String |
| `Wert1, Wert2, Wert3, Wert4` | kein String (Anführungszeichen fehlen) |
## Konkatenation
Mit dem `+`-Operator ist es möglich mehrere Strings zusammenzustellen.
In diesem Beispiel erstellen wir Variablen für eine Begrüßung und stellen wir zusammen.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $greeting = "Willkommen " }}
{{ var $customer = "Neukunde"}}
{{ var $genericGreeting= $greeting + $customer}}
{{= $genericGreeting}} // Wilkommen Neukunde
```
Nur Strings können konkateniert werden. Dennoch ist es möglich andere Variablen in ein String zu konvertieren um sie mit einem String zu konkatenieren.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $menge = 1}}
{{ var $text = "Anzahl: " + string($menge) + "!" }}
{{= $text}} // Anzahl: 1!
```
Es können andere Basistypen in String konvertiert werden:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Boolean: {{= string(true) }} // "true"
Integer: {{= string(1) }} // "1"
Float: {{= string(1.1) }} // "1.1"
```
## Integer
Integer sind Ganzzahlen (Zahlen ohne Nachkommastellen).
| | |
| - | - |
| `10` | Integer |
| `20.00` | kein Integer (Nachkommastellen vorhanden) |
## Float
Floats sind Fließkommazahlen mit einem **Punkt** als Dezimaltrenner.
| | |
| - | - |
| `10.25` | Float |
| `10,25` | kein Float (ungültige Syntax: Komma als Dezimaltrenner) |
### Float konvertieren
Es können andere Basistypen in Float konvertiert werden
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
String: {{= float("1.1")}} // 1.1
Integer: {{= float(1) }} // 1.0
Boolean: {{= float(true) }} // 1.0
```
## Boolean/Bool (true/false)
Ein Bool ist ein Wahrheitswert und kann nur *true* (wahr) oder *false* (falsch) sein.
| | |
| - | - |
| `true` | Wahrheitswert true |
| `false` | Wahrheitswert false |
| `"true"` | kein Wahrheitswert (falsche Syntax: String) |
Boolesche Werte werden meistens in Kombination mit [Vergleichsoperatoren](/frontend/referenz/operatoren) erzeugt. Wenn man beispielsweise einen Wert mit einem anderen vergleicht, ist das Ergebnis entweder wahr oder falsch.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $quantity == 1 }}
Wird angezeigt, wenn der Wert der Variable $quantity gleich 1 ist.
{{ /if }}
```
### truthy und falsy
Nicht nur Werte vom Datentyp Bool enthalten einen Wahrheitswert. Objekte aller anderen Datentypen haben ebenfalls eine Werte-Eigenschaft, die man als *truthy* oder *falsy* bezeichnet. In Zusammenhang mit logischen Operatoren und Verzweigungen ist es wichtig zu wissen, wann ein Wert als wahr oder falsch angesehen wird.
Hier eine Auflistung aller Werte die *falsy* sind und deshalb als *false* behandelt werden:
▪\_null\_, der Wert des Datentyps Null
▪\_false\_
▪die Zahl 0 (*Integer*) oder 0.0 (*Float*)
▪ein leerer *String " "*
▪eine leere *List \[ ]*
▪eine leere *Map*
Alle anderen Werte werden als *truthy* behandelt.
### Boolean konvertieren
Es können andere Basistypen in Boolean konvertiert werden
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
String: {{= bool(" ")}} // true
String: {{= bool("")}} // false
Integer: {{= bool(1) }} // true
Integer: {{= bool(0) }} // false
Float: {{= bool(1.0) }} // true
Float: {{= bool(0.0) }} // false
```
## List
Eine List ist eine Reihe von Werten, die kommasepariert zwischen eckigen Klammern stehen. Eine leere List wird mit eckigen Klammern ohne Inhalt geschrieben.
| | |
| - | - |
| `[1, 2, 3]` | gefüllte List |
| `[ ]` | leere List |
Die Leerzeichen zwischen den Werten sind optional.
## Distinct
Wenn in einer Liste mehrere Einträge gibt, die identisch sind, kann mit dieser Funktion alle doppelten Einträge entfernt werden.
**Argumente**
`list` - Liste, die verarbeitet werden soll
`key` - (Optional) Map-Key, der für den Vergleich mit anderen Maps hergenommen werden soll.
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $list = [ 1, 2, 3, 4, 3, 2, 5, 6, 1 ] }}
{{= distinct($list) }} // Ergebnis: [ 1, 2, 3, 4, 5, 6 ]
{{ $list = [ "a", 1, "b", true, 2, "a", true, true, {"x": 1, "y": 1}, {"x": 1, "y": 2} ] }}
{{= distinct($list) }} // Ergebnis: [ "a", 1, "b", true, 2, , {"x": 1, "y": 1}, {"x": 1, "y": 2} ]
```
Man kann bei für Objekte einen key angeben, mit dem definiert werden soll welches Feld zum Vergleich hergenommen werden soll.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $list = [ 1, {"x": 1, "y": 1}, {"x": 1, "y": 2}, {"x": 2, "y": 2} ] }}
{{= $list | distinct("x") }} // Ergebnis: [ 1, {"x": 1, "y": 1}, {"x": 2, "y": 2} ]
ähnliche Schreibweise ohne Pipe:
{{= distinct($list, "x") }}
```
## Merge
Es können zwei Listen jeweils miteinander vereint werden.
Zusätzliche Information: Neben der Verwendung von einer Funktion kann auch der `+`-Operator (`$list1 + $list2`) verwendet werden.
**Argumente**
`target` - Liste, die für das Zusammenführen als Basis hergenommen werden soll
`source` - Liste, um die das `target` erweitert werden soll
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $list1 = [ 1, 2, 3 ] }}
{{ var $list2 = [ 3, 4, 5] }}
{{ var $list3 = merge($list1, $list2) }}
{{= $list3 }} // Ergebnis: [1, 2, 3, 3, 4, 5]
```
## Map
Eine Map ist eine Liste von Schlüssel-Wert-Paaren, die innerhalb einfacher geschweifter Klammern geschrieben werden. Der Schlüssel und sein Wert werden durch Doppelpunkt getrennt. Die einzelnen Schlüssel-Wert-Paare werden durch Kommas getrennt. Eine leere Map wird mit geschweiften Klammern ohne Inhalt geschrieben.
| | |
| - | - |
| `{ name: "Shirt", price: "12.95", image: "shirt-blue.jpg" }` | gefüllte Map |
| `{ "404": "Not found", "301": "Moved Permanently" }` | gefüllte Map |
| `{ "Name, Description , Price, Zusatzinfos" }` | keine Map (ungültige Syntax) |
| `{ }` | leere Map |
Wenn ein Schlüssel andere Zeichen enthält als Ziffern (0-9), Buchstaben (a-z, A-Z) oder Unterstriche (\_) oder mit einer Ziffer/Unterstrich beginnt, muss dieser als String in Anführungszeichen angegeben werden.
Bei der Ausgabe von Maps wird die Reihenfolge der einzelnen Schlüssel-Werte-Paare nicht berücksichtigt.
### **Merge**
Es können zwei Maps jeweils miteinander vereint werden. Bei der Map wird bei unterschiedlichen Inhalten der Inhalt des zweite Eintrags verwendet. Dabei kann auch verschachtelte Maps berücksichtigt werden.
**Argumente**
`target` - Map, die für das Zusammenführen als Basis hergenommen werden soll
`source` - Map, um die das `target` erweitert werden soll
`deep` - Optionaler Flag ob ein die Verschachtelung von Maps berücksichtigt werden soll (default: `false`)
Beispiel - Merge von zwei Maps.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $map1 = { "a": 1, "b": 2, "c": { "x": 10, "y": 11 } } }}
{{ var $map2 = { "a": 2, "c": { "z": 12 }, "d": true } }}
{{ var $map3 = merge($map1, $map2) }}
{{= $map3 }} // Ergebnis: { "a": 2, "b": 2, "c":{ "z": 12 }, "d": true }
```
Beispiel - Deep Merge von zwei Maps:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $map1 = { "a": 1, "b": 2, "c": { "x": 10, "y": 11 } } }}
{{ var $map2 = { "a": 2, "c": { "z": 12 }, "d": true } }}
{{ var $map3 = merge($map1, $map2, true) }}
{{= $map3 }} // Ergebnis: { "a": 2, "b": 2, "c":{ "x": 10, "y": 11, "z": 12 }, "d": true }
```
# Funktionen
Source: https://dokumentation.websale.de/frontend/referenz/funktionen
Globale Template-Funktionen: Strings anpassen, Zahlen runden, Listen zusammenführen und Datumswerte vergleichen – inklusive Modifier-Nutzung.
Globale Template-Funktionen stehen in allen Templates zur Verfügung. Sie werden verwendet, um Werte zu verarbeiten, zu formatieren oder zu prüfen (z. B. Strings anpassen, Zahlen runden, Listen zusammenführen oder Datumswerte vergleichen).
Auf dieser Seite werden ausschließlich globale Funktionen beschrieben. Funktionen, die an ein Modul gebunden sind, beispielsweise Methoden von `$wsAccount` oder `$wsExternalData`, sind in der jeweiligen [Modul-Referenz](/frontend/referenz/module) dokumentiert.
Viele dieser Funktionen können alternativ auch als [Modifier](/frontend/referenz/modifiers) (Filter) verwendet werden.
***
## Grundlagen
Funktionen werden mit runden Klammern aufgerufen. Werte, die an eine Funktion übergeben werden (sogenannte Parameter), werden durch Kommas getrennt. Funktionsnamen sind case-sensitive. Groß- und Kleinschreibung muss also genau beachtet werden.
### Schreibweise
Damit das Ergebnis einer Funktion im Template ausgegeben wird, wird die Ausgabe-Schreibweise verwendet:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= (...) }}
```
Das Ergebnis der Funktion muss nicht zwingend sofort im Template ausgegeben werden, sondern kann auch in einer eigenen Variable gespeichert werden, um es später weiter zu verwenden.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myVariable = (...) }}
```
### Parameterübergabe und Reihenfolge
Standardmäßig werden Parameter positionsbasiert übergeben (in der Reihenfolge der Signatur).
Wenn die Reihenfolge der Parameter geändert werden soll, müssen benannte Parameter verwendet werden (Name laut Signatur + `=`). Entscheidend sind dann die Parameternamen – nicht die Position.
**Beispiel**
Ein Gutschein soll über die Funktion `replace` umbenannt werden. Aus `GUTSCHEIN_buy10` soll `GUTSCHEIN_sale10` werden.
Die Signatur lautet: `replace(content, search, replace)`. Bei positionsbasierter Übergabe ist die Reihenfolge daher:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= replace("GUTSCHEIN_buy10", "buy", "sale") }}
```
Sobald Parameter benannt übergeben werden (`name="..."`), ist die Reihenfolge frei:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= replace(search="buy", replace="sale", content="GUTSCHEIN_buy10") }}
```
In beiden Fällen ist das Ergebnis:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
GUTSCHEIN_sale10
```
### Funktionen kombinieren (verkettete Verarbeitung)
Mehrere Funktionen können auch nacheinander angewendet werden, indem die erste Funktion als Argument der zweiten Funktion verwendet wird.
**Beispiel**
Die VersandkostenID „versand\_kostenfrei“ soll sprechend in „VERSAND KOSTENFREI“ umbenannt und die Schreibweise in Versalien (Großschreibung) geändert werden.
Es werden die Funktionen `upper` und `replace` verwendet:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= upper(replace("versand_kostenfrei", "_", " ")) }}
```
\=
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
VERSAND KOSTENFREI
```
### Texte und Listen zusammenfügen
Mit dem `+`-Operator können zwei Texte (Strings) direkt zu einem neuen String zusammengefügt werden. Für Listen kann `+` alternativ zu `merge()` verwendet werden, um zwei Auflistungen zu vereinen.
Es können jedoch nur Werte desselben Typs mit `+` verbunden werden. Zahlen oder andere Typen müssen vorher mit der Funktion [string](#string) in einen Text umgewandelt werden.
**Beispiele**\
Artikelnummer aus Präfix und ID zusammensetzen:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $prefix = "ART-" }}
{{ var $productId = "10452" }}
{{ var $articleNumber = $prefix + $productId }}
{{= $articleNumber }}
```
**Ausgabe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
ART-10452
```
Bestellmenge in einen Hinweistext einbinden. Zahlen müssen vor der Zusammensetzung mit einem String mit `string()` in einen Text umgewandelt werden.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $quantity = $wsBasket.totalQuantity }}
{{ var $message = "Anzahl Artikel im Warenkorb: " + string($quantity) }}
{{= $message }}
```
***
## Liste der Funktionen
### abs
Die Funktion `abs` gibt den Absolutwert einer Zahl zurück – also den Wert ohne Vorzeichen. Eine negative Zahl wird dadurch positiv, eine positive Zahl bleibt unverändert.
**Anwendungsbeispiel**\
Nützlich, um z. B. Rabattbeträge oder Preisdifferenzen im Shop immer als positive Zahl darzustellen – unabhängig davon, ob der Wert in den Daten ein Minus-Vorzeichen hat.
**Signatur**\
`abs(value)`
**Parameter**
* `value` - Die Zahl, deren Absolutwert ermittelt werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel mit negativem Wert**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= abs(-7.5) }}
```
**Ausgabe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
7.5
```
**Beispiel mit positivem Wert**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= abs(3) }}
```
**Ausgabe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
3
```
**Beispiel - Preisdifferenz immer positiv darstellen**\
Der aktuelle Preis eines Produkts wird im Feld `price` gespeichert (hier: `79.95`), der ursprüngliche Preis im Feld `setOrgPrice` (hier: `99.95`). Die Differenz zwischen beiden kann je nach Rechenrichtung negativ ausfallen. Mit `abs` wird sichergestellt, dass der angezeigte Betrag immer positiv ist.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myProduct = $wsProducts.load("100-12345") }}
Sie sparen: {{= currency(abs($myProduct.price - $myProduct.setOrgPrice)) }} €
```
**Ausgabe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Sie sparen: 20,00 €
```
***
### ceil
Die Funktion `ceil` rundet eine Zahl immer auf die nächste ganze Zahl auf – egal, wie klein der Nachkommaanteil ist. `ceil(1.1)` ergibt also `2`, genauso wie `ceil(1.9)`.
**Anwendungsbeispiel**\
Hilfreich, wenn Werte im Shop immer „zugunsten" einer ganzen Einheit aufgerundet werden sollen – z. B. Stückzahlen, Verpackungseinheiten oder berechnete Mengen.
**Signatur**\
`ceil(value)`
**Parameter**
* `value` – Die Zahl, die aufgerundet werden soll.
**Verwendbar als Modifier:**\
ja
**Beispiel mit Dezimalzahl resp. Dezimalbruch**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= ceil(1.3) }}
```
**Ausgabe** (aufgerundet auf die nächste ganze Zahl)
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
2.000000
```
**Beispiel mit ganzer Zahl (Ganzzahl)**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= ceil(2) }}
```
**Ausgabe** (ganze Zahl bleibt unverändert)
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
2.000000
```
Um die Darstellung der Nachkommastellen anzupassen benutzen Sie `ceil(2) | preparedFormat(“name“)`
\
**Beispiel - Berechnetes Produktgewicht aufrunden**\
Das Versandgewicht eines Produkts (in diesem Fall 2,3 kg) wird auf volle Kilogramm aufgerundet.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myProductWeight = $myProduct.custom.weight }}
Versandgewicht: {{= ceil($myProductWeight) | preparedFormat("amount") }} kg
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Versandgewicht: 3 kg
```
**Gegenstück**\
[floor](#floor)
***
### currency
Die Funktion `currency` formatiert einen numerischen Wert als Preisangabe gemäß den [Shop-Einstellungen zur Währung](/konfiguration/finance-wahrungen-steuern). Dazu gehören insbesondere:
* Dezimaltrennzeichen (z. B. `,` statt `.`)
* Anzahl der Nachkommastellen (z. B. 2 bei vielen Währungen)
* kaufmännisches Runden auf die konfigurierte Nachkommastellen-Anzahl
Die Funktion berechnet keine Preise (z.B. Steuern, Rabatte oder Versandkosten), sondern formatiert ausschließlich den übergebenen Wert für die Ausgabe.
**Anwendungsbeispiel**\
Eignet sich für die Ausgabe von Beträgen wie Einzelpreisen, Rabatten, Zwischensummen und Gesamtsummen.
**Signatur**\
`currency(price)`
**Parameter**
* `price` - Die Zahl, die als Preis formatiert werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel mit Nachkommastellen**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= currency(3.1475) }}
```
**Ausgabe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
3,15€
```
**Beispiel mit Ganzzahl**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= currency(12) }}
```
**Ausgabe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
12,00€
```
Soll ein Zahlenwert unabhängig von der Währung in einem bestimmten Format ausgegeben werden (z.B. mit einer anderen Anzahl an Nachkommastellen), ist [preparedFormat()](#preparedformat) die passende Funktion.
**Beispiel - Produktpreis formatiert ausgeben**\
Der Preis eines Produkts wird als Dezimalzahl gespeichert (hier: `89.95`). Mit `currency` wird er gemäß den Shop-Einstellungen formatiert.
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
89.95€
```
***
### dateFmt
Die Funktion `dateFmt` bringt ein Datum oder einen Zeitpunkt in ein gewünschtes Anzeigeformat. Der Eingabewert muss im ISO-8601-Format vorliegen (z. B. `2018-03-11T11:20:11.000Z`) – dieses Format wird von den meisten Systemen automatisch verwendet.
**Anwendungsbeispiel**\
Damit lassen sich z. B. Bestelldaten, Liefertermine oder Aktionszeiträume im Shop leserlich darstellen (z. B. als „11.03.2018" oder „11:20:11").
**Signatur**\
`dateFmt(isoDate, fmt[, tz])`
**Parameter**
* `isoDate` – Datum/Zeit im ISO-8601-Format (z. B. `2018-03-11T11:20:11.000Z`)
* `fmt` – Formatangabe, die festlegt, wie die Ausgabe aussehen soll
* Die wichtigsten Platzhalter im Überblick
* `%d` = Tag (01–31)
* `%m` = Monat (01–12)
* `%Y` = Jahr (4-stellig)
* `%H` = Stunde (00–23)
* `%M` = Minute (00–59)
* `%S` = Sekunde (00–60)
* Damit können Sie die folgenden Formate einfach „zusammenbauen“, z. B.:
* `"%d.%m.%Y"` → `11.03.2018`
* `"%H:%M:%S"` → `11:20:11`
* `tz` (optional) – Zeitzone, in der die Zeit ausgegeben werden soll (z.B. "`Europe/Berlin`"). Ohne Angabe wird die im Shop konfigurierte Zeitzone verwendet (Konfiguration [general.general](/konfiguration/general-allgemeine-shopeinstellungen#general-general-allgemeine-basiseinstellungen), auch über [\$wsSubshop.timeZone](/frontend/referenz/module/wssubshop#wssubshop-timezone) abrufbar). Gültige Werte sind die Namen der IANA-Zeitzonendatenbank, [eine gut lesbare Übersicht finden Sie hier](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
**Verwendbar als Modifier**\
ja
**Beispiel zur Ausgabe des Bestelldatums aus der “Bestellzeit”**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= dateFmt("2018-03-11T11:20:11.000Z", "%d.%m.%Y") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
11.03.2018
```
**Beispiel zur Ausgabe der Uhrzeit aus der “Bestellzeit”**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= dateFmt("2018-03-11T11:20:11.000Z", "%H:%M:%OS") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
11:20:11
```
**Beispiel mit Ausgabe der Zeitzone**\
Derselbe UTC-Zeitstempel wird in der Zeitzone `Europe/Berlin` ausgegeben. Im März gilt dort die Mitteleuropäische Zeit (UTC+1), die Uhrzeit liegt daher eine Stunde später als in der UTC-Eingabe.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= dateFmt("2018-03-11T11:20:11.000Z", "%H:%M", "Europe/Berlin") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
12:20
```
**Beispiel - aktuelle Jahreszahl ausgeben**\
In Kombination mit [\$wsSubshop.currentTime](/frontend/referenz/module/wssubshop) (aktueller Zeitstemple im ISO-8601-Format) lässt sich z.B. die aktuelle Jahreszahl ausgeben.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= $wsSubshop.currentTime | dateFmt("%Y") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
2026
```
**Beispiel - Bestelldatum und Uhrzeit formatiert ausgeben**\
Das Bestelldatum ist in diesem Beispiel in folgendem Format gespeichert - `2024-06-15T14:32:05.000Z`. Mit `dateFmt` wird es für eine Bestellbestätigung in ein lesbares Datum und eine separate Uhrzeit umgewandelt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{var $myOrder = $wsOrderHistory.load($wsViews.current.params.orderHistorySelect)}
Bestellt am: {{= dateFmt($myOrder.general.dateTime, "%d.%m.%Y") }}
Uhrzeit: {{= dateFmt($myOrder.general.dateTime, "%H:%M") }} Uhr
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Bestellt am: 15.06.2024
Uhrzeit: 14:32 Uhr
```
***
### dateGreaterThan
Die Funktion `dateGreaterThan` vergleicht zwei Datumswerte (als Strings) miteinander und liefert `true`, wenn das erste Datum nach dem zweiten Datum liegt.
**Anwendungsbeispiel**\
Damit lässt sich im Template z. B. prüfen, ob ein Liefertermin in der Zukunft liegt oder ob ein Zeitraum bereits überschritten ist.
**Signatur**\
`dateGreaterThan(firstDate, secondDate)`
**Parameter:**
* `firstDate` – Erstes Datum (zu prüfender Wert)
* `secondDate` – Zweites Datum (Vergleichswert)
**Verwendbar als Modifier**\
ja
**Beispiel eines Datumsvergleichs**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= dateGreaterThan("2019-03-11T11:20:11.000Z", "2017-07-11T11:20:11.000Z") }}
```
**Ausgabe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
true
```
**Beispiel - Prüfen, ob eine Bestellung nach einem bestimmten Stichtag aufgegeben wurde**\
Mit `dateGreaterThan` lässt sich prüfen, ob die Bestellung nach einem festen Stichtag liegt - z.B. um nur Bestellungen ab dem 01.01.2025 für eine Rückgabeaktion zu berücksichtigen.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myOrder = $wsOrderHistory.load("12345") }}
{{ var $stichtag = "2025-01-01T00:00:00.000Z" }}
{{ if (dateGreaterThan($myOrder.general.dateTime, $stichtag)) }}
Diese Bestellung ist für die Rückgabeaktion qualifiziert.
{{ /if }}
```
**Ausgabe, wenn das Bestelldatum nach dem 01.01.2025 liegt**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Diese Bestellung ist für die Rückgabeaktion qualifiziert.
```
**Gegenstück**\
[dateLessThan](#datelessthan)
***
### dateLessThan
Die Funktion `dateLessThan` vergleicht zwei Datumswerte (als Strings) miteinander und liefert `true`, wenn das erste Datum **vor** dem zweiten Datum liegt.
**Anwendungsbeispiel**\
Damit lassen sich im Template z. B. Fristen oder Zeiträume prüfen - etwa ob ein Datum bereits überschritten ist oder ob ein Ereignis noch bevorsteht.
**Signatur**\
`dateLessThan(firstDate, secondDate)`
**Parameter**
* `firstDate` – Erstes Datum (zu prüfender Wert)
* `secondDate` – Zweites Datum (Vergleichswert)
**Verwendbar als Modifier**\
ja
**Beispiel eines Datumsvergleichs**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= dateLessThan("2020-03-11T11:20:11.000Z", "2021-07-11T11:20:11.000Z") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
true
```
**Beispiel - Hinweis anzeigen, wenn eine Bestellung vor einem Stichtag aufgegeben wurde**\
Mit `dateLessThan` lässt sich prüfen, ob die Bestellung vor einem festen Stichtag liegt - z.B. um drauf hinzuweisen, dass die Rückgabefrist bereits abgelaufen ist.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myOrder = $wsOrderHistory.load("12345") }}
{{ var $fristEnde = "2025-01-01T00:00:00.000Z" }}
{{ if (dateLessThan($myOrder.general.dateTime, $fristEnde)) }}
Die Rückgabefrist für diese Bestellung ist abgelaufen.
{{ /if }}
```
**Ausgabe, wenn das Bestelldatum vor dem 01.01.2025 liegt**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Die Rückgabefrist für diese Bestellung ist abgelaufen.
```
**Gegenstück**\
[dateGreaterThan](#dategreaterthan)
***
### decode
Die Funktion `decode` wandelt einen kodierten String zurück in seinen ursprünglichen Klartext. Unterstützte Formate sind `base64` und `hex`. Wenn der übergebene Wert kein gültiger kodierter String im angegebenen Format ist, gibt die Funktion `null` zurück.
**Anwendungsbeispiel**\
Nutzbar, um z.B. extern kodiert übermittelte Produktdaten, Gutscheincodes oder Konfigurationswerte vor der Weiterverarbeitung im Template zu dekodieren.
**Signatur**\
`decode(content, format)`
**Parameter**
* `content` - Der kodierte String, der dekodiert werden soll.
* `format` - Das Kodierungsformat, das beim Dekodieren verwendet werden soll. Gültige Werte: `“base64”`, `“hex”`.
**Verwendbar als Modifier**\
ja
**Beispiel - Dekodierung eines Base64-Strings**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= decode("d2Vic2FsZQ==", "base64") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
websale
```
**Beispiel - Dekodierung eines Hex-Strings**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= decode("776562 73616c65", "hex") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
websale
```
**Beispiel - Fehlerhafte Eingabe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= decode("kein-gültiger-base64-wert!!!", "base64") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
null
```
**Gegenstück**\
[encode](#encode)
***
### distinct
Die Funktion `distinct` entfernt doppelte Einträge aus einer Auflistung und gibt eine neue Auflistung zurück, in der jeder Wert nur einmal vorkommt. Bei Auflistungen von Datenobjekten (Maps) kann optional ein Schlüssel angegeben werden, anhand dessen verglichen wird. Die Angabe des Schlüssels wird nur auf der obersten Ebene einer Map berücksichtigt.
**Anwendungsbeispiel**\
Nutzbar, um z.B. Duplikate aus einer Liste von Produktkategorien, Variantenmerkmalen oder Filterwerten zu entfernen, bevor sie im Template angezeigt werden.
**Signatur**\
`distinct(list[, key]`
**Parameter**
* `list` - Die Auflistung, aus der Duplikate entfernt werden sollen.
* `key (optional)` - Schlüssel eines Datenobjekts, der für den Vergleich verwendet wird.
**Verwendbar als Modifier**\
ja
**Beispiel - Doppelte Größenangaben aus einer Variantenliste entfernen**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $sizes = ["S", "M", "L", "M", "XL", "S"] }}
{{= distinct($sizes) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
["S", "M", "L", "XL"]
```
***
### encode
Die Funktion `encode` kodiert einen String ein ein angegebenes Format. Unterstützte Formate sind `base64` und `hex`. Der Rückgabewert ist immer vom Typ String.
**Anwendungsbeispiel**\
Nutzbar, um z.B. Gutscheincodes, Produkt-Kennungen oder andere Werte für die Weitergabe an externe Dienste oder in URLs sicher zu kodieren.
**Signatur**\
`encode(content, format)`
**Parameter**
* `content` - Der String, der kodiert werden soll.
* `format` - Das Zielformat der Kodierung. Gültige Werte: `“base64”`, `“hex”`.
**Verwendbar als Modifier**\
ja
**Beispiel - Kodierung als Base64**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= encode("websale", "base64") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
d2Vic2FsZQ==
```
**Beispiel - Kodierung als hex**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= encode("websale", "hex") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
776562 73616c65
```
**Gegenstück**\
[decode](#decode)
***
### floor
Die Funktion `floor` rundet eine Zahl immer auf die nächste ganze Zahl ab – egal, wie groß der Nachkommaanteil ist. `floor(4.9)` ergibt also `4`, genauso wie `floor(4.1)`.
**Anwendungsbeispiel**\
Hilfreich, wenn Werte im Shop grundsätzlich abgerundet werden sollen – z. B. bei berechneten Mengen oder Zwischenergebnissen, die nur als ganze Zahl weiterverarbeitet werden dürfen.
**Signatur**\
`floor(value)`
**Parameter**
* `value` – Numerischer Wert, der abgerundet werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel mit Dezimalzahl resp. Dezimalbruch**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= floor(4.9) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
4.000000
```
**Beispiel mit ganzer Zahl**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= floor(2) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
2.000000
```
Um die Darstellung der Nachkommastellen anzupassen benutzen Sie `floor(4.9) | preparedFormat(“name”)`
**Beispiel - Berechnetes Produktgewicht abrunden**\
Das Versandgewicht eines Produkts (in diesem Fall 2,7 kg) wird auf volle Kilogramm abgerundet.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myProductWeight = $myProduct.custom.weight }}
Mindestgewicht: {{= floor($myProductWeight) | preparedFormat("amount") }} kg
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Mindestgewicht: 2 kg
```
**Gegenstück**\
[ceil](#ceil)
***
### ifnull
Die Funktion `ifnull` prüft, ob ein Wert vorhanden ist oder nicht (`null` bedeutet: „kein Wert vorhanden"). Ist der Wert `null`, wird stattdessen ein Ersatzwert ausgegeben. Ist ein Wert vorhanden, wird dieser selbst verwendet.
**Anwendungsbeispiel**\
Eignet sich z.B. für Fallback-Logiken im Shop - etwa um ein Ersatzbild anzuzeigen, wenn kein Produktbild vorhanden ist, oder um fehlende Produktdaten durch Standardwerte zu ersetzen.
**Signatur**\
`ifnull(object, value)`
**Parameter**
* `object` - Der zu prüfende Wert.
* `value` - Der Alternativwert, der ausgegeben wird, wenn `object` den Wert `null` hat.
**Verwendbar als Modifier**\
ja
**Beispiel mit** `null`**-Wert**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= ifnull(Null, "sale") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
sale
```
**Beispiel mit vorhandenem Wert**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= ifnull("web", "sale") }}
```
**Ausgabe** (der String `“web”` ist nicht `null`, daher wird er selbst ausgegeben).
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
web
```
**Beispiel mit Produktbild-Fallback**\
In der Variable `$myProduct` werden alle Informationen und Daten zu einem Produkt gespeichert. Wenn kein Produktbild gefunden wird (`$myProduct.custom.image.normal` ist `null`), dann wird das Ersatzbild `noImageNormal.png` angezeigt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myProduct = $wsView.info.product }}
```
***
### int
Die Funktion `int` wandelt einen Wert in eine ganze Zahl (Integer) um. Das ist vor allem dann nötig, wenn ein Zahlenwert als Text vorliegt (z.B. `“10”`) und als echte Zahl weiterverarbeitet werden soll - etwa für Berechnungen oder Vergleiche. Ist die Umwandlung nicht möglich (z.B. bei einem Wort), wird `null` zurückgegeben. Dezimalzahlen werden auf die ganze Zahl vor dem Komma gekürzt (nicht gerundet).
**Anwendungsbeispiel**\
Nutzbar, um z. B. Mengenangaben oder Artikel-IDs, die als Text vorliegen (z.B. “1043”), in eine Zahl umzuwandeln, bevor sie weiterverarbeitet werden.
**Signatur**\
`int(value)`
**Parameter**
* `value` - Der Wert, der in eine Ganzzahl konvertiert werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel mit einem String, der eine Zahl enthält**
Der Text “10” wird in die Zahl 10 umgewandelt. Mit der Ausgabe wurde der Text in eine Zahl konvertiert, mit der nun gerechnet werden kann.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= int("10") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
10
```
**Beispiel mit nicht konvertierbarem Wert**
Ein Wort (in diesem Fall “websale”) kann nicht ein eine Zahl umgewandelt werden - die Ausgabe ist `null`.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= int("websale") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
null
```
**Beispiel mit Dezimalzahl**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= int(10.789) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
10
```
***
### isoToUnix
Die Funktion `isoToUnix` wandelt einen Zeitstempel im ISO-8601-Format in die Unix-Zeit um, also die Anzahl der Sekunden seit dem 1.Jahnuar 1970 (UTC).\
\
**Anwendungsbeispiel**\
Nutzbar, um z.B. Zeitstempel für Berechnungen, Vergleiche oder die Übergabe an externe Dienste in ein einheitliches numerisches Format zu bringen.\
\
**Signatur**\
`isoToUnix(isoDate)`
**Parameter**
* `isoDate` - Zeitstempel im ISO-8601-FOrmat (z.B. 2018-03-11T11:20:11.000Z)
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= isoToUnix("2018-03-11T11:20:11.000Z") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
1520767211
```
**Gegenstück**
[unixToIso](#unixtoiso)
***
### join
Die Funktion `join` fügt alle Einträge einer Auflistung zu einem String zusammen. Optional kann ein Separator (Trennzeichen) angegeben werden, der die Elemente voneinander trennt.
**Anwendungsbeispiel**\
Eignet sich z. B. um Produkteigenschaften, Variantenmerkmale oder Kategorien als zusammenhängenden Text auszugeben – etwa kommasepariert in einer Zeile.
**Signatur**\
`join(list[, "separator"])`
**Parameter**
* `list` - Die Auflistung, deren Einträge zusammengefügt werden sollen.
* `separator` (optional) - Trennzeichen zwischen den Einträgen. Standard: kein Trennzeichen.
**Verwendbar als Modifier**\
ja
**Beispiel ohne Separator**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= join(["S", "M", "L", "XL"]) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
SMLXL
```
**Beispiel mit Separator**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= join(["S", "M", "L", "XL"], ", ") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
S, M, L, XL
```
**Beispiel - verfügbare Farben eines Produkts als Text ausgeben**\
Die Varianten-Daten eines Produkts werden über `$wsProducts.variantInfo()` geladen. Das Attribut “Farbe” enthält eine Auflistung von Optionen (hier: `“Rot”`, `“Blau”`, `“Grün”`). Die Farbnamen werden in einer Schleife gesammelt, mit [push](#push) in einer Auflistung gesammelt und mit `join` zu einem lesbaren Text zusammengefügt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myVariants = $wsProducts.variantInfo("100-12345") }}
{{ var $colors = [] }}
{{ for $myOption in $myVariants.variantAttributes[0].options }}
{{ push($colors, $option.name) }}
{{ /for }}
Verfügbare Farben: {{= join($colors, ", ") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Verfügbare Farben: Rot, Blau, Grün
```
**Gegenstück**\
[split](#split)
***
### json
Die Funktion `json` gibt ein Datenobjekt in der technischen JSON-Schreibweise aus – einem standardisierten Textformat, das sich leicht maschinell verarbeiten lässt.
**Anwendungsbeispiel**\
Nützlich zum Fehlersuchen (Debugging) im Template oder bei der Weitergabe von Daten an externe Dienste (z. B. Tracking, Analytics).
**Signatur**\
`json(object)`
**Parameter**
* `object` - Das Objekt, das als JSON-String ausgegeben werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel - Ausgabe von Produktdaten zur Fehlersuche**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $product = $wsView.info.product }}
{{= json($product) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{"name":"Sneaker Classic","price":89.95,"sku":"SNK-001","sizes":["40","41","42"]}
```
Es werden nicht mehr als fünf Ebenen ausgegeben. Tiefere Ebenen werden als `“…”` dargestellt.
***
### keys
Die Funktion `keys` gibt alle Bezeichner (Schlüssel) eines Datenobjekts (Map) als Auflistung zurück. Eine Map besteht aus Paaren von Bezeichnern und Werten – z. B. `{name: "Topseller", price: 12.99}`. Mit `keys` lassen sich gezielt die Bezeichner auslesen.
**Anwendungsbeispiel**\
Nutzbar, um z. B. über alle Einträge eines Datenobjekts zu gehen und sowohl die Bezeichner als auch die zugehörigen Werte im Template anzuzeigen – etwa bei dynamisch aufgebauten Produktdaten oder Konfigurationseinstellungen.
**Signatur**\
`keys(object)`
**Parameter**
* `object` - Das Datenobjekt, dessen Bezeichner (Schlüssel) zurückgegeben werden sollen.
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= keys({name: "Topseller", price: 12.99, description: "Beschreibung"}) }}
```
**Ausgabe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
["description","price","name"]
```
***
### last
Die Funktion `last` gibt den letzten Eintrag einer Auflistung (List) zurück.
**Anwendungsbeispiel**\
Nutzbar, um z.B. die letzte Bestellposition, den letzten Breadcrumb-Eintrag oder das letzte Element einer Variantenliste gezielt anzuzeigen.
**Signatur**\
`last(list)`
**Parameter**
* `list` - die Auflistung, deren letzter Eintrag zurückgegeben werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= last(["a", "b", "c", "d"]) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
d
```
**Beispiel - Letzten Breadcrumb-Eintrag als aktuelle Kategorie anzeigen**\
Der Kategoriepfad (Breadcrumb) wird über `$wsCategories.loadPath()` als Auflistung geladen. Mit `last` wird der letzte Eintrag gezielt ausgelesen, da dieser der aktuellen Kategorie entspricht.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myBreadcrumb = $wsCategories.loadPath($category.id) }}
Kategorie: {{= last($myBreadcrumb).name }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Sneaker
```
***
### len
Die Funktion `len` ermittelt die Länge, also die Anzahl der Zeichen bei einem Text, die Anzahl der Einträge bei einer Auflistung oder die Anzahl der Schlüssel-Wert-Paare bei einem Datenobjekt.
**Anwendungsbeispiel**\
Nutzbar, um z.B. die Anzahl von Produkten in einer Liste zu zählen, die Zeichenlänge einer Eingabe zu prüfen oder um festzustellen, wie viele Einträge ein Datenobjekt enthält.
**Signatur**\
**len(sequence)**
**Parameter**
* `sequence` - Text, Auflistung oder Datenobjekt, dessen Länge ermittelt werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel mit Text**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= len("abc def. XYZ") }}
```
**Ausgabe** (Anzahl der Zeichen)
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
12
```
**Beispiel mit Auflistung**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= len([1, 2, 3]) }}
```
**Ausgabe** (Anzahl der Einträge)
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
3
```
**Beispiel mit Datenobjekt**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= len({name: "Produkt", price: 12.99}) }}
```
**Ausgabe** (Anzahl der Schlüssel-Wert-Paare)
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
2
```
**Beispiel - Anzahl der Produkte in einer Kategorie anzeigen**\
Die Produkte einer Kategorie werden über [\$wsCategories.loadProducts()](/frontend/referenz/module/wscategories#\$wscategories-loadproducts) geladen (hier: 24 Produkte in der Kategorie). Mit `len` wird die Anzahl ermittelt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $products = $wsCategories.loadProducts("100-12345") }}
{{= len($products) }} Produkte gefunden
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
24 Produkte gefunden
```
***
### lower
Die Funktion `lower` wandelt alle Buchstaben eines Textes in Kleinbuchstaben um.
**Anwendungsbeispiel**\
Nutzbar, um z.B. Benutzereingaben, Gutscheincodes oder Produktkennungen einheitlich in Kleinschreibung darzustellen oder zu vergleichen.
**Signatur**\
`lower(content)`
**Parameter**
* `content` - der Text, der in Kleinbuchstaben umgewandelt werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= lower("TOPSELLER") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
topseller
```
**Gegenstück**\
[upper](#upper)
***
### max
Die Funktion `max` gibt den höchsten Wert aus einer Auflistung von Zahlen zurück.
**Anwendungsbeispiel**\
Nutzbar, um z.B. den teuersten Preis innerhalb einer Variantenliste oder die höchste verfügbare Menge zu ermitteln.
**Signatur**\
`max(list)`
**Parameter**
* `list` - die Auflistung mit Zahlenwerten.
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= max([5, 13, -1, 3, 2, -7, 12]) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
13
```
**Beispiel - Höchsten Bestellwert aus der Bestellhistorie ermitteln**\
Die letzten Bestellungen eines Kunden werden über `$wsOrderHistory.loadList()` geladen. Jede Bestellung enthält u. a. das Feld `order.total` (Gesamtpreis). Die geladenen Bestellwerte werden mit [push](#push) in einer eigenen Auflistung gesammelt und anschließend mit `max` der höchste Wert ermittelt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myOrders = $wsOrderHistory.loadList() }}
{{ var $myTotals = [] }}
{{ for $myOrder in $myOrders }}
{{ push($myTotals, $myOrder.order.total) }}
{{ /for }}
Ihre höchste Bestellung: {{= max($myTotals) | currency }} €
```
**Ausgabe** (bei Bestellwerten `49.90`, `129.00`, `89.95`):
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Ihre höchste Bestellung: 129,00 €
```
**Gegenstück**\
[min](#min)
***
### merge
Die Funktion `merge` führt zwei Datenobjekte (Maps) zusammen. Die Einträge aus dem zweiten Objekt (`source`) werden in das erste Objekt (`target`) übernommen. Bei Listen werden die Einträge der zweiten Liste an die erste angehängt. Es wird kein neues Objekt erzeugt, das erste Objekt wird direkt verändert.
Für Maps steht optional der Parameter `deep` zur Verfügung. Bei `deep=true` werden verschachtelte Maps ebenfalls zusammengeführt, anstatt überschrieben zu werden.
**Anwendungsbeispiel**\
Nutzbar, um z.B. Standardwerte für die Produktanzeige mit produktspezifischen Werten zusammenzuführen. So können z.B. Standardtext oder Fallback-Bilder definiert werden, die nur dann zum Einsatz kommen, wenn ein Produkt keinen eigenen Wert hat.
**Signatur**\
`merge(target, source[, deep=false])`
**Parameter**
* `target` - das Ziel-Objekt, in das die Einträge eingefügt werden.
* `source` - das Quell-Objekt, dessen Einträge übernommen werden.
* `deep` (optional) - nur für Maps. Bei `true` werden verschachtelte Maps ebenfalls zusammengeführt.
**Verwendbar als Modifier**\
ja
**Beispiel - Standardwerte mit produktspezifischen Daten zusammenführen**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $defaults = {"badge": "Neu", "shipping": "Standardversand"} }}
{{ var $productData = {"badge": "Sale", "color": "rot"} }}
{{= merge($defaults, $productData) }}
```
**Ausgabe**
```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{"badge": "Sale", "shipping": "Standardversand", "color": "rot"}
```
Wenn beide Objekte denselben Bezeichner (Schlüssel) enthalten, wird der Wert aus dem ersten Objekt durch den Wert aus dem zweiten Objekt überschrieben.
**Beispiel - Produktdaten mit verschachtelten Standardwerten zusammenführen** (`deep merge`)
Standardwerte für ein Produkt enthalten auch verschachtelte Bilddaten (`image`). Mit `deep=true` werden diese beim Zusammenführen nicht vollständig überschrieben, sondern ebenfalls zusammengeführt - sodass nur die tatsächlich vom Produkt gelieferten Bildpfade übernommen werden, fehlende aber durch den Standardwert erhalten bleiben.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $defaults = {"badge": "Neu", "shipping": "Standardversand", "image": {"normal": "noImageNormal.png", "thumb": "noImageThumb.png"}} }}
{{ var $productData = {"badge": "Sale", "image": {"normal": "sneaker-normal.png"}} }}
{{= merge($defaults, $productData, true) }}
```
**Ausgabe (das Thumbnail aus den Standardwerten bleibt erhalten, weil das Produkt keines mitliefert)**
```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{"badge": "Sale", "shipping": "Standardversand", "image": {"normal": "sneaker-normal.png", "thumb": "noImageThumb.png"}}
```
***
### min
Die Funktion `min` gibt den niedrigsten Wert aus einer Auflistung von Zahlen zurück.
**Anwendungsbeispiel**\
Nutzbar, um z.B. den günstigsten Preis innerhalb einer Variantenliste oder den kleinsten Bestand zu ermitteln.
**Signatur**\
`min(list)`
**Parameter**
* `list` - die Auflistung mit Zahlenwerten.
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= min([5, 13, -1, 3, 2, -7, 12]) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
-7
```
**Beispiel - Niedrigsten Bestellwert aus der Bestellhistorie ermitteln**\
Die letzten Bestellungen eines Kunden werden über [\$wsOrderHistory.loadList()](/frontend/referenz/module/wsorderhistory#\$wsorderhistory-loadlist) geladen. Jede Bestellung enthält u. a. das Feld `order.total` (Gesamtpreis). Die Bestellwerte werden mit [push](#push) in einer eigenen Auflistung gesammelt, anschließend wird mit `min` der niedrigste Wert ermittelt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myOrders = $wsOrderHistory.loadList() }}
{{ var $myTotals = [] }}
{{ for $myOrder in $myOrders }}
{{ push($myTotals, $myOrder.order.total) }}
{{ /for }}
Ihre niedrigste Bestellung: {{= min($myTotals) | currency }} €
```
**Ausgabe** (bei Bestellwerten `49.90`, `129.00`, `89.95`):
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Ihre niedrigste Bestellung: 49,90 €
```
**Gegenstück**\
[max](#max)
***
### preparedFormat
Die Funktion `preparedFormat` formatiert eine Zahl hinsichtlich Dezimaltrennzeichen und Nachkommastellen, basierend auf einem [im Shop hinterlegten Format](/konfiguration/general-allgemeine-shopeinstellungen#12-general-numberformat-zahlen-und-preisformatierung).
**Anwendungsbeispiel**
Nutzbar, um z.B. Mengenangaben, Gewichte oder andere Zahlenwerte shopgerecht darzustellen.
**Signatur**\
`preparedFormat(number, formatName)`
**Parameter**
* `number` - Die Zahl, die formatiert werden soll.
* `name` - Name des im Shop konfigurierten Formats (z.B. `“amount”`).
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= preparedFormat(3.5, "amount") }}
```
**Ausgabe** (`amount` formatiert hier auf ganze Zahlen)
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
4
```
**Beispiel - Produktgewicht formatiert ausgeben**\
Das Gewicht eines Produkts ist im Feld `$myProduct.custom.weight` als Dezimalzahl gespeichert (hier: `2.300000`). Mit `preparedFormat` wird es gemäß dem im Shop hinterlegten Format `"weight"` ausgegeben.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $weight = $myProduct.custom.weight }}
Gewicht: {{= preparedFormat($weight, "weight") }} kg
```
**Ausgabe** (bei einem Gewicht von `2.300000` und Format `"weight"` mit einer Nachkommastelle):
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Gewicht: 2,3 kg
```
***
### push
Die Funktion `push` fügt ein neues Element am Ende einer bestehenden Liste hinzu und gibt die neue Anzahl der Einträge in der Auflistung zurück. Die Liste wird dabei direkt verändert, es wird keine neue Liste erzeugt.
**Anwendungsbeispiel**\
Nutzbar, um z.B. in einer Schleife gezielt Einträge zu sammeln, etwa gefilterte Produkte, Fehlermeldungen oder dynamisch zusammengestellte Ausgabelisten.
**Signatur**\
`push(list, element)`
**Parameter**
* `list` - Die Auflistung, an die das neue Element angehängt werden soll.
* `element` - Der Wert, der hinzugefügt werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel - Element hinzufügen**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myWishlist = ["ART-100", "ART-205"] }}
{{ push($myWishlist, "ART-310") }}
{{= $myWishlist }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
["ART-100", "ART-205", "ART-310"]
```
**Beispiel - Rückgabewert nutzen**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myWishlist = [] }}
{{ push($myWishlist, "ART-100") }}
{{ var $amount = push($myWishlist, "ART-205") }}
{{= $amount }}
```
**Ausgabe (Anzahl der Einträge nach dem Hinzufügen)**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
2
```
**Beispiel - Produkte einer Kategorie laden und Produkte aus einer anderen Kategorie ergänzen**\
Die Produkte einer Kategorie werden über `$wsCategories.loadProducts()` als Auflistung geladen. Mit `push` können Produkte aus einer zweiten Kategorie an die Liste angehängt werden - z.B. um Cross-Selling-Artikel in die Ausgabe aufzunehmen.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myProducts = $wsCategories.loadProducts("100-12345") }}
{{ var $myCrossSelling = $wsCategories.loadProducts("100-99999") }}
{{ for $item in $myCrossSelling }}
{{ push($myProducts, $item) }}
{{ /for }}
{{ for $product in $myProducts }}
{{= $product.name }}
{{ /for }}
```
Die Auflistung `$myProducts` enthält nun alle Produkte der ersten Kategorie plus die Produkte aus der Cross-Selling-Kategorie.
***
### random
Die Funktion `random` erzeugt einen Zufallswert.
**Anwendungsbeispiel**\
Nutzbar, um z.B. zufällige Gutscheincodes zu Erzeugen.
**Hinweis**\
Die Funktion ist geplant, wird aber momentan noch nicht unterstützt.
***
### range
Die Funktion `range` erzeugt eine Auflistung von aufeinanderfolgenden ganzen Zahlen - vom Startwert bis zum Endwert. Standardmäßig wird in Einserschritten gezählt. Bei absteigenden Reihen muss eine negative Schrittweite angegeben werden.
**Anwendungsbeispiel**\
Nutzbar, um z.B. Seitenumbrüche (Pagination), Mengenwähler oder nummerierte Ausgaben im Template zu erzeugen.
**Signatur**\
`range(start, stop[, step=1])`
**Parameter**
* `start` - Startwert der Zahlenreihe.
* `stop` - Endwert der Zahlenreihe.
* `step` (optional) - Schrittweite (Standard: 1). Für absteigend zählende Reihen einen negativen Wert verwenden.
**Verwendbar als Modifier**\
nein
**Beispiel für eine aufsteigende Reihe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= range(1, 5) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[1, 2, 3, 4, 5]
```
**Beispiel für eine absteigende Reihe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= range(10, 2, -2) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[10, 8, 6, 4, 2]
```
***
### raw
Die Funktion `raw` gibt einen Wert ohne automatische Bereinigung von HTML-Zeichen aus, sodass enthaltener HTML-Code vom Browser als Formatierung interpretiert wird, statt als reiner Text an gezeigt zu werden.
**Anwendungsbeispiel**\
Nutzbar, um z.B. formatierte Produktbeschreibungen oder CMS-Inhalte mit HTML-Markup unverändert im Shop darzustellen.
**Hinweis**\
Die Funktion ist geplant, wird aber momentan noch nicht unterstützt.
***
### replace
Die Funktion `replace` ersetzt in einem Text alle Vorkommen eines Suchbegriffs durch einen anderen Text.
**Anwendungsbeispiel**\
Nutzbar, um z.B. interne Bezeichnung für die Anzeige im Shop leserlicher zu machen.
**Signatur**\
`replace(string, search, replace)`
**Parameter**
* `content` - Der Ausgangstext.
* `search` - Der Text, der gesucht und ersetzt werden soll.
* `replace` - Der Text, der stattdessen eingesetzt werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= replace("webbuy", "buy", "sale") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
websale
```
***
### reverse
Die Funktion `reverse` kehrt die Reihenfolge der Zeichen in einem Text oder der Einträge in einer Auflistung um.
**Anwendungsbeispiel**\
Nutzbar, um z.B. eine bestehende Sortierung umzukehren oder Einträge in umgekehrter Reihenfolge auszugeben (z.B. neueste Einträge zuerst).
**Hinweis**\
Die Funktion ist geplant, wird aber momentan noch nicht unterstützt.
***
### round
Die Funktion `round` rundet eine Zahl kaufmännisch auf oder ab. Optional kann die gewünschte Anzahl an Nachkommastellen angegeben werden. Ohne Angabe wird auf eine ganze Zahl gerundet.
**Anwendungsbeispiel**\
Nutzbar, um z.B. berechnete Zwischenwerte, Gewichte oder Mengen kaufmännisch gerundet im Template anzuzeigen.
**Signatur**\
`round(number[, precision=0])`
**Parameter**
* `number` - Die Zahl, die gerundet werden soll.
* `precision` (optional) - Gewünschte Anzahl an Nachkommastellen (Standard: 0).
**Verwendbar als Modifier**\
ja
**Beispiel ohne Nachkommastellen**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= round(3.1415) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
3.000000
```
**Beispiel mit 2 Nachkommastellen**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= round(1.2345, 2) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
1.230000
```
**Anzeige mit zwei Nachkommastellen**
Der Parameter `precision` steuert die mathematische Rundung (auf wie viele Nachkommastellen der Wert gerundet wird). Die Ausgabe zeigt jedoch systembedingt immer bis zu sechs Nachkommastellen an (z.B: `1.230000` statt `1.23`). Um die Darstellung anzupassen (z.B. nur 2 sichtbare Nachkommastellen), wird `round` in Kombination mit [preparedFormat](#preparedformat) verwendet:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= round(1.2345, 2) | preparedFormat("name") }}
```
***
### sort
Die Funktion `sort` sortiert die Einträge einer Auflistung (List). Standardmäßig wird aufsteigend sortiert. Mit dem optionalen Parameter `reverse` kann die Sortierung aber auch umgekehrt werden.
**Anwendungsbeispiel**\
Nutzbar, um z.B. Produktlisten, Varianten oder Filteroptionen alphabetisch oder nach Zahlenwert zu sortieren.
**Signatur**\
`sort(list[, reverse=false])`
**Parameter**
* `list` - Die Auflistung, deren Einträge sortiert werden sollen.
* `reverse`(optional) - Bei `true` wird absteigend sortiert.
**Verwendbar als Modifier**\
ja
**Beispiel mit Zahlen**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= sort([5, 2, 8, 1, 4]) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[1.0, 2.0, 4.0, 5.0, 8.0]
```
**Beispiel mit Texten**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= sort(["Hose", "Accessoire", "Jacke"]) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
["Accessoire", "Hose", "Jacke"]
```
**Beispiel - Preise absteigend sortieren**
Wenn die Liste nur aus Zahlen besteht, werden alle Elemente nach der Sortierung den Typ `float` haben.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $prices = [49.90, 129.00, 19.95, 89.95] }}
{{= sort($prices, true) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[129.000000, 89.950000, 49.900000, 19.950000]
```
**Beispiel - Verfügbare Farben eines Produkts alphabetisch sortieren**\
Die varianten-Daten eines Produkts werden über `$wsProducts.variantInfo()` geladen. Das Attribut “Farbe” enthält eine Auflistung von Optionen (hier: `Rot, Blau, Grün, Beige`). Da die Optionen als Objekte vorliegen (z.B. `{name: “Rot”}`), werden die Namen zunächst mit [push](#push) in einer eigenen Auflistung gesammelt. Anschließend werden sie mit `sort` alphabetisch sortiert und in einer Schleife ausgegeben.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myVariants = $wsProducts.variantInfo("100-12345") }}
{{ var $colors = [] }}
{{ for $myOption in $myVariants.variantAttributes.options }}
{{ push($colors, $myOption.name) }}
{{ /for }}
{{ var $sortedColors = sort($colors) }}
{{ for $color in $sortedColors }}
{{= $color }}
{{ /for }}
```
***
### split
Die Funktion `split` teilt einen Text anhand eines Trennzeichens in eine Auflistung (List) einzelner Einträge auf.
**Anwendungsbeispiel**\
Nutzbar, um z.B. kommaseparierte Werte aus Produktdaten, Konfigurationen oder externen Quellen in einzelne Einträge zu zerlegen und getrennt zu verarbeiten.
**Signatur**\
`split(content, separator)`
**Parameter**
* `content` - Der Text, der aufgeteilt werden soll.
* `separator` - Das Trennzeichen, an dem der Text aufgeteilt wird.
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= split("vegan,glutenfrei,laktosefrei,bio", ",") }}
```
**Ausgabe**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
["vegan", "glutenfrei", "laktosefrei", "bio"]
```
**Gegenstück**\
[join](#join)
***
### startswith
Die Funktion `startswith` prüft, ob ein Text mit einer bestimmten Zeichenfolge beginnt und gibt `true` oder `false` zurück.
**Anwendungsbeispiel**\
Nutzbar, um z.B. Artikelnummern anhand ihrer Anfangszeichen zu unterscheiden und im Template darauf zu reagieren, etwa um Produkte bestimmter Produktgruppen unterschiedlich darzustellen (z.B. alle Artikelnummern, die mit `“TKK”` beginnen, als Tiefkühlprodukte zu kennzeichnen).
**Signatur**\
`startswith(str, prefix)`
**Parameter**
* `str` - Der Text, der geprüft werden soll.
* `prefix` - Die Zeichenfolge, auf die am Textanfang geprüft wird.
**Verwendbar als Modifier**\
ja
**Beispiel mit einem Treffer**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= startswith("TKK-40210", "TKK") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
true
```
**Beispiel ohne Treffer**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= startswith("BKL-10050", "TKK") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
false
```
**Beispiel - Produkte anhand der Artikelnummer einer Produktgruppe zuordnen**
Die Artikelnummer eines Produkts steht im Feld `itemNumber` (hier: `“TKK-40210”`). Artikelnummern, die mit `“TKK”` beginnen, gehören zur Produktgruppe Tiefkühlware. Mit `startswith` wird dies geprüft und ein entsprechendes Badge angezeigt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myProduct = $wsProducts.load("100-12345") }}
{{ if (startswith($myProduct.itemNumber, "TKK")) }}
Tiefkühlprodukt
{{ /if }}
```
**Ausgabe** (bei Artikelnummer `“TKK-40210”`)
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Tiefkühlprodukt
```
***
### static
Die Funktion `static` erzeugt den vollständigen Pfad zu einer statischen Datei (z.B. JavaScript, CSS, Bilder). Standardmäßig liegen solche Dateien unter `media/themes/default` auf dem Server des Shops.
**Anwendungsbeispiel**\
Nutzbar, um z.B. Pfade zu statischen Dateien im Template korrekt einzubinden - auch, wenn sich der Speicherort später ändert.
**Signatur**\
`static(path)`
**Parameter**
* `path` - Pfad zur Datei, relativ zum Static-Verzeichnis des Shops.
**Verwendbar als Modifier**\
nein
**Beispiel**\
Statt eines fest eingetragenen Pfads:
```javascript theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
```
wird empfohlen, `static` zu verwenden:
```javascript theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
```
Durch die konsequente Nutzung von `static` kann der Speicherort der statischen Dateien jederzeit angepasst werden (z.B. auf einen Media-Server oder ein CDN), ohne dass die Templates geändert werden müssen. Bei Kategorie- oder Produktbildern wird `static` nicht benötigt - deren Pfade werden automatisch korrekt erzeugt.
***
### string
Die Funktion `string` wandelt einen Wert in einen Text (String) um. Zwar sieht das Ergebnis bei Zahlen identisch aus, intern ist es jedoch ein String, also kein Zahlenwert mehr, mit dem gerechnet werden könnte. Der Wert kann anschließend mit textbasierten Funktionen wie `replace`, `startswith` oder `split` weiterverarbeitet werden.
**Anwendungsbeispiel**\
Nutzbar, um beispielsweise eine Artikelnummer, die als Zahl vorliegt, in einen Text umzuwandeln, damit anschließend mit `startswith` geprüft werden kann, ob sie mit einer bestimmten Zeichenfolge beginnt.
**Signatur**
`string(content)`
**Parameter**
* `content` - Der Wert, der in Text umgewandelt werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel mit ganzer Zahl**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= string(42) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
42
```
**Beispiel mit Dezimalzahl**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= string(12.99) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
12.99
```
***
### stripHtml
Die Funktion `stripHtml` entfernt alle HTML-Formatierungen (Tags) aus einem Text und gibt nur den reinen Textinhalt zurück.
**Anwendungsbeispiel**\
Nutzbar, um beispielsweise HTML-formatierte Produktbeschreibungen als reinen Text auszugeben.
**Signatur**
`stripHtml(content)`
**Parameter**
* `content` - Der Text, aus dem die HTML-Formatierungen entfernt werden sollen.
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= stripHtml("Unser Topseller im Shop!
") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Unser Topseller im Shop!
```
***
### take
Die Funktion `take` gibt die ersten Zeichen eines Textes oder die ersten Einträge einer Auflistung zurück.
**Anwendungsbeispiel**\
Nutzbar, um z.B. nur die ersten Zeichen eines Produktnamens oder die ersten Einträge einer Produktliste anzuzeigen.
**Signatur**\
`take(content, count)`
**Parameter**
* `content` - Der Text oder die Auflistung, aus der die ersten Elemente entnommen werden sollen.
* `count` - die Anzahl der Zeichen bzw. Einträge, die vom Anfang genommen werden.
**Verwendbar als Modifier**\
ja
**Beispiel mit Text**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= take("websale", 3) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
web
```
**Beispiel mit Auflistung**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= take([1, 2, 3, 4, 5], 3) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[1, 2, 3]
```
**Beispiel - Nur die ersten 4 Produkte einer Kategorie anzeigen**\
Die Produkte einer Kategorie werden über [\$wsCategories.loadProducts()](/frontend/referenz/module/wscategories#\$wscategories-loadproducts) als Auflistung geladen (hier: `24 Produkte`). Mit `take` werden in diesem Beispiel nur die ersten 3 Einträge entnommen und in einer Schleife als Teaser ausgegeben.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $myProducts = $wsCategories.loadProducts("100-12345") }}
{{ var $myTopProducts = take($myProducts, 3) }}
{{ for $product in $myTopProducts }}
{{= $product.name }}
{{ /for }}
```
**Ausgabe** (bei Produkten `"Sneaker Classic"`, `"Laufschuh Pro"`, `"Sandale Sport"`, `"Wanderstiefel"`, …)
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Sneaker Classic
Laufschuh Pro
Sandale Sport
```
**Gegenstück**
[takeLast](#takelast)
***
### takeLast
Die Funktion `takeLast` gibt die letzten Zeichen eines Textes oder die letzten Einträge einer Auflistung zurück.
**Anwendungsbeispiel**\
Nutzbar, um z.B. die letzten Zeichen einer Bestellnummer oder die letzten Einträge einer Liste gezielt anzuzeigen.
**Signatur**\
`takeLast(content, count)`
**Parameter**
* `content` - Der Text oder die Auflistung, aus der die letzten Elemente entnommen werden sollen.
* `count` - Die Anzahl der Zeichen bzw. Einträge, die vom Ende genommen werden.
**Verwendbar als Modifier**\
ja
**Beispiel mit Text**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= takeLast("12345", 2) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
45
```
**Beispiel mit Auflistung**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= takeLast([1, 2, 3, 4, 5], 2) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[4, 5]
```
**Beispiel - Die letzten 2 Ebenen des Breadcrumb-Pfads anzeigen**\
Der Kategoriepfad (`Breadcrumb`) wird über [\$wsCategories.loadPath()](/frontend/referenz/module/wscategories#\$wscategories-loadpath) als Auflistung geladen (hier: 4 Ebenen). Mit `takeLast` werden nur die letzten 2 Einträge entnommen - z.B. um in einer Unternavigation nur die aktuelle und die übergeordnete Kategorie anzuzeigen.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $breadcrumb = $wsCategories.loadPath($category.id) }}
{{ var $lastTwo = takeLast($breadcrumb, 2) }}
{{ for $cat in $lastTwo }}
{{= $wsViews.url('Category', {id: $cat.id}) }}">{{= $cat.name }}
{{ /for }}
```
**Ausgabe** (bei einem Pfad “Startseite → Damen → Schuhe → Sneaker”):
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Schuhe
Sneaker
```
**Gegenstück**\
[take](#take)
***
### translate
Die Funktion `translate` gibt den Text eines [Textbausteins](/admin-interface/templates-und-content/textbausteine) zur Laufzeit aus. Im Gegensatz zur Schreibweise `%%Textbausteinname%%` muss die Bezeichnung des Textbausteins dabei nicht fest im Template stehen. Sie kann auch erst beim Aufruf der Seite entstehen, beispielsweise aus einem Wert, den ein externes System liefert.
**Anwendungsbeispiel**
Nutzbar, um beispielsweise zu einem Statuscode eines externen Systems den passenden Text auszugeben, etwa zum Lieferstatus einer Bestellung. Für jeden möglichen Status wird ein Textbaustein angelegt. Das Template setzt die Bezeichnung aus einem festen Präfix und dem Statuscode zusammen.
**Signatur**
`translate(variable, language)`
**Parameter**
* `variable` - Die Bezeichnung des Textbausteins.
* `language` - Optional. Die ID der Sprache, deren Text ausgegeben werden soll, beispielsweise `en`. Es gilt die ID, unter der die Sprache in der Konfiguration [general.language](/konfiguration/general-allgemeine-shopeinstellungen) angelegt ist. Ohne diesen Parameter wird die Sprache des aktuellen Subshops verwendet.
**Rückgabewert**
Der Text des Textbausteins. Fehlt der Text in der gewählten Sprache oder ist er leer, greifen die [Ersatzsprachen](/admin-interface/templates-und-content/textbausteine#3-ersatzsprachen-hinterlegen) dieser Sprache, wie bei `%%Textbausteinname%%`. Ist der Text in allen Sprachen dieser Reihe leer, liefert die Funktion einen leeren Text. Gibt es den Textbaustein nicht oder ist die angegebene Sprache im Shop nicht angelegt, liefert die Funktion `null`.
**Verwendbar als Modifier**
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= translate("shop.basket.addButton") }}
```
**Ausgabe** im deutschen Subshop
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
In den Warenkorb
```
**Beispiel mit Angabe der Sprache**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= translate("shop.basket.addButton", "en") }}
```
**Ausgabe** unabhängig von der Sprache des Subshops
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Add to cart
```
**Beispiel mit zusammengesetzter Bezeichnung**
Ein externes System liefert den Lieferstatus einer Bestellung als Code, der in der Variable `$statusCode` gespeichert wird. Ein Beispiel hierfür ist der Code `shipped`. Für jeden Code ist ein Textbaustein angelegt, beispielsweise `deliveryStatus.shipped` mit dem Text „Versendet“. Die Klammern sorgen dafür, dass die Bezeichnung zuerst zusammengesetzt und erst danach übersetzt wird. Mit [ifnull](#ifnull) wird ein Ersatztext ausgegeben, falls zu einem Code kein Textbaustein existiert. Einen vorhandenen, aber leeren Textbaustein ersetzt `ifnull` nicht.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= ("deliveryStatus." + $statusCode) | translate | ifnull("Status unbekannt") }}
```
**Ausgabe** für den Code `shipped`
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Versendet
```
Wenn der Statuscode eine Zahl ist, wandeln Sie ihn vorher mit der Funktion [string](#string) in einen Text um, beispielsweise `"deliveryStatus." + string($statusCode)`. Mit `+` lassen sich nur Werte desselben Typs verbinden.
Die Ausgabe mit `{{= ... }}` unterliegt dem [Standard-Escaping](/frontend/die-basics/template-engine#standard-escaping). Enthält der Textbaustein HTML, beispielsweise einen Zeilenumbruch oder eine Hervorhebung aus dem Editor, wird dies als Klartext angezeigt. Wenn die Formatierung erhalten bleiben soll, geben Sie den Text mit `{{! ... }}` aus.
Textbausteine, die ausschließlich über `translate` eingebunden sind, gelten in der Textbaustein-Übersicht als nicht verwendet. Die Verwendung wird erst bei der Template-Kompilierung für die Schreibweise `%%Textbausteinname%%` ermittelt. Löschen Sie solche Bausteine daher nicht beim Aufräumen, weil `translate` an dieser Stelle sonst `null` liefert.
***
### trim
Die Funktion `trim` entfernt überflüssige Leerzeichen am Anfang und Ende eines Textes.
**Anwendungsbeispiel**\
Nutzbar, um z.B. Benutzereingaben, importierte Produktdaten oder externe Werte vor der Weiterverarbeitung von ungewollten Leerzeichen zu bereinigen.
**Hinweis**\
Die Funktion ist geplant, wird aber momentan noch nicht unterstützt.
***
### type
Die Funktion `type` Gibt den Datentyp eines Wertes als Text zurück - also z. B. ob es sich um einen Text (`string`), eine ganze Zahl (`int`), eine Dezimalzahl (`float`), eine Auflistung (`list`) oder ein Datenobjekt (`map`) handelt.
**Anwendungsbeispiel**\
Nutzbar, um z.B. auf Fehlersuche zu gehen (Debugging) oder um im Template zu prüfen, ob ein Wert den erwarteten Typ hat, bevor er weiterverarbeitet wird.
**Signatur**\
`type(object)`
**Parameter**
* `object` - Der Wert, dessen Datentyp ermittelt werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel anhand eines Textes**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= type("Websale") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
String
```
**Beispiel anhand einer Kommazahl**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= type(1.27) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Float
```
***
### unixToIso
Die Funktion `unixToIso` wandelt eine Unix-Zeit (Anzahl der Sekunden seit dem 1. Januar 1970, UTC) in einen Zeitstempel im ISO-8601-Format um.
**Anwendungsbeispiel**
Nutzbar, um beispielsweise eine von einem externen System gelieferte Unix-Zeit in das im Shop übliche ISO-8601-Format zu bringen. Anschließend kann das Format mit [dateFmt](#datefmt) angepasst werden.
**Signatur**\
`unixToIso(timestamp)`
**Parameter**
* `timestamp` - Unix-Zeit (Anzahl der Sekunden seit dem 1. Januar 1970, UTC).
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= unixToIso(1520767211) }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
2018-03-11T11:20:11.000Z
```
**Gegenstück**
[isoToUnix](#isotounix)
***
### upper
Die Funktion `upper` wandelt alle Buchstaben eines Textes in Großbuchstaben um.
**Anwendungsbeispiel**\
Nutzbar, um z.B. Gutscheincodes, Versandarten oder Überschriften einheitlich und in Großschreibung darzustellen.
**Signatur**\
`upper(content)`
**Parameter**
* `content` - Der Text, der in Großbuchstaben umgewandelt werden soll.
**Verwendbar als Modifier**\
ja
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= upper("Topseller") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
TOPSELLER
```
**Gegenstück**\
[lower](#lower)
***
## Modifier
Viele Funktionen können alternativ auch als [Modifier (Filter)](/frontend/referenz/modifiers#modifiers) in der Filterschreibweise verwendet werden.
Dabei steht der erste Parameter links vom Pipe-Operator `|`, weitere Parameter werden in Klammern angegeben.
Alternativ kann eine Funktion auch mit dem Filter-Operator | (pipe) notiert werden (= Filterschreibweise). Dabei steht der erste Parameter links vom Operator.
**Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= "webbuy" | replace("buy", "sale") }}
```
**Ausgabe**
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
websale
```
# Kontrollstrukturen
Source: https://dokumentation.websale.de/frontend/referenz/kontrollstrukturen
Kontrollstrukturen und Boolean-Werte: Wahrheitswerte true und false sowie Bedingungen für die Steuerung von Template-Ausgaben einsetzen.
## Boolean/Bool (true/false)
Ein Bool ist ein Wahrheitswert und kann nur *true* (wahr) oder *false* (falsch) sein.
| | |
| - | - |
| `true` | Wahrheitswert true |
| `false` | Wahrheitswert false |
| `"true"` | kein Wahrheitswert (falsche Syntax: String) |
Boolesche Werte werden meistens in Kombination mit Vergleichsoperatoren erzeugt. Wenn man beispielsweise einen Wert mit einem anderen vergleicht, ist das Ergebnis entweder wahr oder falsch.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $quantity == 1 }}
Wird angezeigt, wenn der Wert der Variable $quantity gleich 1 ist.
{{ /if }}
```
## truthy und falsy
Nicht nur Werte vom Datentyp Bool enthalten einen Wahrheitswert. Objekte aller anderen Datentypen haben ebenfalls eine Werte-Eigenschaft, die man als *truthy* oder *falsy* bezeichnet. In Zusammenhang mit logischen Operatoren und Verzweigungen ist es wichtig zu wissen, wann ein Wert als wahr oder falsch angesehen wird.
Hier eine Auflistung aller Werte die *falsy* sind und deshalb als *false* behandelt werden:
▪*null*, der Wert des Datentyps Null
▪*false*
▪die Zahl 0 (*Integer*) oder 0.0 (*Float*)
▪ein leerer *String " "*
▪eine leere *List \[ ]*
▪eine leere *Map*
Alle anderen Werte werden als *truthy* behandelt.
## Boolean konvertieren
Es können andere Basistypen in Boolean konvertiert werden
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
String: {{= bool(" ")}} // true
String: {{= bool("")}} // false
Integer: {{= bool(1) }} // true
Integer: {{= bool(0) }} // false
Float: {{= bool(1.0) }} // true
Float: {{= bool(0.0) }} // false
```
# Loops
Source: https://dokumentation.websale.de/frontend/referenz/loops
Schleifen und Verzweigungen in Templates: if, elseif, else, switch sowie foreach für die bedingte und wiederholte Template-Ausgabe nutzen.
Mit Hilfe von Kontrollstrukturen kannst Du die Ausgabe abhängig machen von bestimmten Bedingungen. Man unterscheidet zwischen Verzweigungen mit *if* oder *switch* und der *foreach*-Schleife.
## if-Verzweigung
Mit einer *if*-Verzweigung werden eine oder mehrere Bedingungen geprüft. Je nachdem, welche Bedingung als erstes ein *true* zurückgibt, wird dieser Zweig angezeigt und die restlichen werden ignoriert. Eine *if*/*elseif*/*else*-Verzweigung muss immer aus einem *if*-Zweig und optional beliebig viele *elseif*-Zweige bestehen sowie optional einem einzigen *else*-Zweig.
Eine Verzweigung wird mit *if* eingeleitet und durch */if* abgeschlossen. *elseif*- und *else*-Zweige werden dagegen nicht explizit geschlossen.
Das folgende Beispiel zeigt die unterschiedlichen Anredeformen, wenn Bestandskunden im Shop angemeldet sind. Auf dem Template sei eine Variable *\$geschlecht* definiert, die sich das entsprechende Geschlecht aus den Kundendatensätzen holt.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $geschlecht == "männlich" }}
Sehr geehrter Herr {{= $customer.lastName }},
{{ elseif $geschlecht == "weiblich" }}
Sehr geehrte Frau {{= $customer.lastName }},
{{ else }}
Sehr geehrte Damen und Herren,
{{ /if }}
```
## switch-Verzweigung
Alternativ zu *if*-Verzweigungen kannst Du auch *switch*, *case* und *default* verwenden. Mit *switch* leitest Du die Verzweigung ein und gibst an, welches Feld geprüft werden soll. Hinter *case* schreibst Du ohne *==* die unterschiedlichen Werte und *default* entspricht *else*.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ switch $geschlecht }}
{{ case "männlich" }}
Sehr geehrter Herr {{= $customer.lastName }},
{{ case "weiblich" }}
Sehr geehrte Frau {{= $customer.lastName }},
{{ default }}
Sehr geehrte Damen und Herren,
{{ /switch }}
```
## foreach-Schleife
Eine *foreach*-Schleife dient dazu, Codeabschnitte mehrfach zu wiederholen (*iterieren*). Die Schleife wird mit *foreach* eingeleitet und mit */foreach* geschlossen. Der umschlossene Bereich wird für jedes Element des iterierbaren Objekts einmal ausgeführt. Mit jedem Durchlauf wird das aktuelle Element des iterierbaren Objekts der sogenannten Laufvariable (im Beispiel unten *\$product)* ohne *var* zugewiesen.
Im folgenden Beispiel enthält *\$productList* eine List mit 3 Elementen. Mit jedem Durchlaufen der Schleife wird das jeweilige Element mit den HTML-Tags ausgegeben.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $productList = ["Hemd", "Bluse", "Hose"] }}
{{ foreach $product in $productList }}
Produkt: {{= $product }}
{{ /foreach }}
```
Es wird folgender HTML-Quellcode erzeugt:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Produkt: Hemd
Produkt: Bluse
Produkt: Hose
```
Das Iterieren mit einer *foreach*-Schleife ist mit *Strings*, *Lists* und *Maps* möglich.
Die *foreach*-Schleife ist der einzige Schleifentyp der Template Engine. Andere Schleifen wie *for*, *while* oder *do-while* gibt es nicht.
### Schleifenzähler
Die Template Engine stellt innerhalb einer *foreach*-Schleife keine automatische Zählervariable bereit. Eine Variable wie `$loop.index` existiert nicht. Wenn Du die Position des aktuellen Elements benötigst, definierst Du vor der Schleife eine eigene Variable mit `var` und zählst sie am Ende jedes Durchlaufs hoch.
Das folgende Beispiel fügt nach dem zweiten Produkt (also an dritter Stelle) einen Platzhalter in die Produktliste ein. Danach läuft die Schleife normal weiter.
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $index = 0 }}
{{ foreach $product in $productList }}
Produkt: {{= $product }}
{{ if $index == 1 }}
{{ /if }}
{{ var $index = $index + 1 }}
{{ /foreach }}
```
Da der Zähler bei `0` startet, entspricht `$index == 1` dem zweiten Element.
# Modifiers
Source: https://dokumentation.websale.de/frontend/referenz/modifiers
Modifiers (Filter) in der Template-Sprache: Werte bei der Ausgabe formatieren, Strings anpassen, Zahlen runden und Listen umwandeln.
Diese Seite beschreibt die Grundlagen und Schreibweise von Modifiers. Modifiers (auch Filter genannt) werden verwendet, um Werte im Template direkt bei der Ausgabe oder Weiterverarbeitung zu verändern, zu formatieren oder zu prüfen – zum Beispiel Texte anpassen, Zahlen runden oder Listen umwandeln.
***
## Grundlagen & Schreibweise
Modifiers werden nicht als eigenständiger Funktionsaufruf geschrieben, sondern auf einen bestehenden Wert angewendet.
Ein Modifier verarbeitet immer den Wert, der links von ihm steht. Das Ergebnis kann direkt ausgegeben oder in einer Variablen gespeichert und später weiterverwendet werden.
Modifiers werden mit dem Pipe-Operator `|` an einen Wert „angehängt“:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= | }}
```
Wenn ein Modifier zusätzliche Parameter benötigt, werden diese in runden Klammern angegeben:
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= | (, , ...) }}
```
## Übersicht der Modifier
Eine vollständige Liste aller verfügbaren Modifiers wird hier nicht separat geführt, da nahezu alle globalen Funktionen aus der Referenzseite [Funktionen](/frontend/referenz/funktionen) zusätzlich auch als Modifier verwendet werden können.
## Beispiele
### **Beispiel** `upper`
Wert in Großbuchstaben ausgeben
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= "Sneaker Classic" | upper }}
```
\=
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
SNEAKER CLASSIC
```
### **Beispiel** `replace` und `lower`
Wert für URL/Slug vorbereiten (Leerzeichen ersetzen + Kleinschreibung)
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{= "Sneaker Classic" | replace(" ", "-") | lower }}
```
\=
```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
sneaker-classic
```
# Module - Übersicht
Source: https://dokumentation.websale.de/frontend/referenz/module
Übersicht der WEBSALE-Module wie $wsAccount, $wsBasket oder $wsProducts: Variablen und Methoden für die Template-Ausgabe von Shopdaten.
Module sind von **WEBSALE** vorgegebene, global verfügbare Module (z. B. `$wsAccount`). Sie stellen Variablen (Eigenschaften) und Methoden bereit. In der Entwicklung werden sie teilweise auch als `View-Module` bezeichnet, da sie primär für die Ausgabe (Leseseite) verwendet werden.
Mit diesen Modulen stehen Shopdaten für die Template-Ausgabe zur Verfügung, z. B. zu Produkten, Kategorien oder Käuferdaten.
Eigene Module können nicht erstellt oder erweitert werden.
***
## Schreibweise & Zugriff
* **Schreibweise:** `$ws` (z. B. `$wsAccount`, `$wsBasket`, `$wsProduct`)
* Module enthalten Variablen (Eigenschaften) und Methoden
* Der Zugriff erfolgt über den Punkt-Operator (`.`), z. B. auf Eigenschaften oder Methoden eines Moduls
* Datenfelder und Funktionen werden einheitlich über `.` angesprochen
**Syntax-Beispiel**
```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
$ws.