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

# BPO- (Freie Felder auf Split-Positions-Ebene)

> Die Tags für freie Eingabefelder und Checkboxen auf Split-Positionsebene: Felder ausgeben, Eingaben zurücklesen und die daran hängenden Zusatzkosten anzeigen.

Mit den freien Feldern auf Split-Positionsebene bieten Sie dem Käufer Eingabefelder und Checkboxen an, die nicht zum Produkt gehören, sondern zur Bestellung: eine Geschenkverpackung, ein Wunschtermin, ein Grußtext. An jedes dieser Felder lassen sich Zusatzkosten hängen.

Anders als bei den freien Eingabefeldern der Warenkorbposition (`BASKET-PR-AdditionalUserInput_1…20`) wird hier alles in der Shopkonfiguration `shop.config` im Abschnitt `<BasketProductOptions>` festgelegt: welche Felder es gibt, wo sie erscheinen, was sie kosten und wie die Eingabe geprüft wird. Die Tags mit dem Präfix `BPO-` geben diese Konfiguration im Template aus.

Wegweiser: [Freie Felder auf Split-Positionsebene](https://dokumentation.websale.de/v8s/referenz/tags/bpo.md) · Referenz: Abschnitt `<[BasketProductOptions](/v8s/referenz/konfigurationen/shopkonfiguration-shop-config/warenkorb-und-bestellprozess#basketproductoptions)>`

## Der Aufbau im Template

Alle Tags dieser Gruppe stecken ineinander, und die Reihenfolge der Schachtelung ist vorgegeben.

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Data}                      Schleife über die konfigurierten Felderblöcke
   {BPO-LevelOfUsage_XXX}        Weiche auf die eingestellte Verwendungsebene
      {@BPO-Input}               Schleife über die Felder dieses Blocks
      {@BPO-Costs}               Schleife über die Kostenberechnungen dieses Blocks
```

Das mittlere Bereichs-Tag ist der Grund, warum derselbe Codeblock auf drei Templates funktioniert. Der Shop kennt nur eine aktive Verwendungsebene, und `BPO-LevelOfUsage_XXX` sorgt dafür, dass der Block nur auf dem dazu passenden Template etwas ausgibt.

Je Shop ist immer nur eine Verwendungsebene aktiv. Sie können also nicht gleichzeitig ein Feld je Bestellung und ein Feld je Warenkorbposition anbieten.

## Das vollständige Beispiel

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Data}
   {BPO-LevelOfUsage_BasketPosition}

      {@BPO-Input}
         {BPO-Input_Type_Input}
            <input type="text" name="~BPO-Input_input~"
                   {BPO-Input_value}value="~BPO-Input_value~"{/BPO-Input_value}>
         {/BPO-Input_Type_Input}

         {BPO-Input_Type_Checkbox}
            <input type="checkbox" name="~BPO-Input_input~"
                   {BPO-Input_value}checked{/BPO-Input_value}>
            <input type="checkbox" name="~BPO-Input_input~_hidden" style="display:none" checked>
         {/BPO-Input_Type_Checkbox}

         {BPO-Input_error}
            <span class="fehler">~BPO-Input_error~</span>
         {/BPO-Input_error}
      {/@BPO-Input}

      {@BPO-Costs}
         {BPO-Costs_Valid}
            {BPO-Costs_Sum}
               {BPO-Costs_Name}~BPO-Costs_Name~: {/BPO-Costs_Name}
               ~BPO-Costs_Sum~ ~WS-CurrencySymbol~
            {/BPO-Costs_Sum}
         {/BPO-Costs_Valid}
      {/@BPO-Costs}

   {/BPO-LevelOfUsage_BasketPosition}
{/@BPO-Data}

<input type="submit" value="speichern" name="~BT-BPO_Refresh~">
```

> [!WARNING]
>
> Ohne die Schaltfläche `BT-BPO_Refresh` gehen die Eingaben verloren. Sie schreibt die Werte in den Warenkorb zurück. Die einzige Ausnahme ist die Produktdetailansicht: dort stehen die Felder innerhalb von `~FORM-Product~` und werden zusammen mit dem Produkt in den Warenkorb übernommen.

Referenz: [BT-BPO\_Refresh](https://dokumentation.websale.de/v8s/referenz/tags/bt/produkt-und-warenkorb.md#schaltflachen-die-anderswo-beschrieben-sind)

## Die Verwendungsebene

Welche der drei Ebenen gilt, legt der Parameter `LevelOfUsage` im Abschnitt `<BasketProductOptions>` fest. Jede Ebene hat ihr eigenes Bereichs-Tag und ihren eigenen Platz im Template.

| Bereichs-Tag | Die Felder gelten | Gehört auf |
| - | - | - |
| `BPO-LevelOfUsage_Once` | einmal für die gesamte Bestellung | Warenkorbseite (`ws_basket.htm`), außerhalb von `{BASKET-PR-Data}` |
| `BPO-LevelOfUsage_BasketPosition` | je Warenkorbposition | Produktdetailansicht (`ws_product.htm`) innerhalb von `~FORM-Product~`, oder Warenkorbseite innerhalb von `{@BASKET-PR-Data}` |
| `BPO-LevelOfUsage_BasketPositionAddress` | je Lieferadresse einer Warenkorbposition | Bestellübersichtsseite (`ws_place_order.htm`), innerhalb von `{@BASKET-PR-D-MultiData}` und `{BASKET-PR-D-SingleData}` |

### BPO-UseOnce

Klammert bei der Ebene `Once` den gesamten Block. Es steht eine Stufe über `BPO-Data` und ist das einzige Tag dieser Gruppe, das außerhalb der Schleife steht.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{BPO-UseOnce}
   {@BPO-Data}
      {BPO-LevelOfUsage_Once}
         <!-- Felder und Kosten -->
      {/BPO-LevelOfUsage_Once}
   {/@BPO-Data}
{/BPO-UseOnce}
```

Die beiden Tags wirken auf den ersten Blick doppelt gemoppelt. `BPO-UseOnce` gehört aber zur Warenkorbseite und hält den Block aus der Positionsschleife heraus, `BPO-LevelOfUsage_Once` prüft die Einstellung des einzelnen Felderblocks. Bei den anderen beiden Ebenen entfällt `BPO-UseOnce`.

### BPO-LevelOfUsage\_BasketPositionAddress

Greift, wenn die Felder je Lieferadresse innerhalb einer Warenkorbposition gelten. Das setzt die Funktion Split-Order voraus, also das Aufteilen einer Position auf mehrere Lieferadressen.

> [!WARNING]
>
> Der Block muss auf der Bestellübersichtsseite zweimal stehen: einmal in `{@BASKET-PR-D-MultiData}` und einmal in `{BASKET-PR-D-SingleData}`. Der Käufer kann auch bei aktiver Split-Order für eine Position nur eine Lieferadresse wählen, und dann greift der zweite Bereich.

Wegweiser: Eine Warenkorbposition aufteilen und an mehrere Lieferadressen senden · Referenz: [BASKET-PR-D-MultiData](https://dokumentation.websale.de/v8s/referenz/tags/basket/mehrfach-lieferadressen-und-belegexemplare.md#was-eingestellt-wurde), [BASKET-PR-D-SingleData](https://dokumentation.websale.de/v8s/referenz/tags/basket/mehrfach-lieferadressen-und-belegexemplare.md#was-eingestellt-wurde)

## Die Schleife über die Felderblöcke

### BPO-Data

Schleife über die in `<BasketProductOptions>` konfigurierten Felderblöcke. Je Durchlauf stehen die Felder und die Kostenberechnungen eines Blocks zur Verfügung.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Data}
   {BPO-LevelOfUsage_XXX}
      <!-- Felder und Kosten dieses Blocks -->
   {/BPO-LevelOfUsage_XXX}
{/@BPO-Data}
```

Alle übrigen Tags dieser Gruppe außer `BPO-UseOnce` und `BPO-AllCosts_Sum` sind nur innerhalb dieser Schleife zulässig. Außerhalb liefern sie nichts, weil ihnen der Bezug zum Felderblock fehlt.

### BPO-ID

Gibt den Bezeichner des Felderblocks aus, also den Wert von `BasketProductOptionID` aus der Shopkonfiguration.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Data}
   <div data-bpo="~BPO-ID~">
      ...
   </div>
{/@BPO-Data}
```

Für den Käufer ist der Bezeichner ohne Bedeutung. Nützlich ist er als Haken für CSS und JavaScript, wenn mehrere Felderblöcke unterschiedlich aussehen sollen.

## Die Eingabefelder

### BPO-Input

Schleife über die Felder des Blocks. Als Einzel-Tag gibt es die Anzahl der konfigurierten Felder aus.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Data}
   Anzahl der Felder: ~BPO-Input~

   {@BPO-Input}
      <!-- ein einzelnes Feld -->
   {/@BPO-Input}
{/@BPO-Data}
```

### BPO-Input\_Type\_Input und BPO-Input\_Type\_Checkbox

Die beiden Bereichs-Tags unterscheiden die Feldart. `BPO-Input_Type_Input` greift beim Texteingabefeld, `BPO-Input_Type_Checkbox` bei der Checkbox.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Input}
   {BPO-Input_Type_Input}
      <input type="text" name="~BPO-Input_input~"
             {BPO-Input_value}value="~BPO-Input_value~"{/BPO-Input_value}>
   {/BPO-Input_Type_Input}

   {BPO-Input_Type_Checkbox}
      <input type="checkbox" name="~BPO-Input_input~"
             {BPO-Input_value}checked{/BPO-Input_value}>
      <input type="checkbox" name="~BPO-Input_input~_hidden" style="display:none" checked>
   {/BPO-Input_Type_Checkbox}
{/@BPO-Input}
```

> [!WARNING]
>
> Das zweite, versteckte Feld bei der Checkbox ist kein Schreibfehler. Ein nicht angehakter Haken schickt gar nichts ab, der Shop könnte also nicht zwischen "abgewählt" und "Formular nie abgeschickt" unterscheiden. Das Feld mit dem Zusatz `_hidden` ist immer gesetzt und meldet, dass dieser Haken überhaupt im Formular stand. Ohne dieses Feld lässt sich eine einmal gesetzte Checkbox nicht wieder abwählen.

### BPO-Input\_ID und BPO-Input\_input

`BPO-Input_ID` gibt den Bezeichner des Feldes aus der Shopkonfiguration aus, `BPO-Input_input` den technischen Feldnamen für das `name`-Attribut.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Input}
   <label for="~BPO-Input_ID~">Ihr Wunsch</label>
   <input type="text" id="~BPO-Input_ID~" name="~BPO-Input_input~">
{/@BPO-Input}
```

> [!WARNING]
>
> Das `name`-Attribut muss aus `BPO-Input_input` kommen. Ein selbst vergebener Name wird beim Absenden nicht erkannt, und die Eingabe ist verloren.

### BPO-Input\_value

Gibt zurück, was der Käufer eingetragen hat. Beim Texteingabefeld ist das der Text, bei der Checkbox der Wert `on`. Als Bereichs-Tag greift es, sobald das Feld ausgefüllt beziehungsweise angehakt ist.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Input}
   {BPO-Input_value}
      Ihre Angabe: ~BPO-Input_value~
   {/BPO-Input_value}

   {!BPO-Input_value}
      Noch keine Angabe gemacht.
   {/!BPO-Input_value}
{/@BPO-Input}
```

Auf der Bestellübersichtsseite ist die Ausgabe ohne Eingabefeld sinnvoll, damit der Käufer seine Angaben vor dem Absenden noch einmal sieht. Dafür genügen `BPO-Data`, `BPO-Input` und `BPO-Input_value` ohne die `LevelOfUsage`-Klammerung.

### BPO-Input\_error

Gibt die Fehlermeldung aus, die in der Shopkonfiguration für die Eingabeprüfung dieses Feldes hinterlegt ist. Als Bereichs-Tag greift es nur, wenn die Prüfung tatsächlich fehlgeschlagen ist.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Input}
   <input type="text" name="~BPO-Input_input~">

   {BPO-Input_error}
      <span class="fehler">~BPO-Input_error~</span>
   {/BPO-Input_error}
{/@BPO-Input}
```

Die Meldung stammt aus dem Abschnitt `<GenericInputChecks>`, verknüpft über den Parameter `+UseGenericInputCheck` des Feldes. Sie gehört direkt neben das Feld und nicht an den Seitenkopf, sonst sucht der Käufer bei mehreren Feldern das falsche.

Referenz: Abschnitt `<[GenericInputChecks](/v8s/referenz/konfigurationen/shopkonfiguration-shop-config/adressen-und-eingabepruefung#genericinputchecks)>`

### BPO-Input\_costs

Gibt die Zusatzkosten aus, die an diesem einen Feld hängen.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Input}
   <input type="checkbox" name="~BPO-Input_input~">
   Geschenkverpackung
   {BPO-Input_costs}(~BPO-Input_costs~ ~WS-CurrencySymbol~){/BPO-Input_costs}
{/@BPO-Input}
```

Das ist die Ausgabe am Feld, nicht die Abrechnung. Den tatsächlich berechneten Betrag liefert `BPO-Costs_Sum`, die Summe über alle Felderblöcke `BPO-AllCosts_Sum`.

## Die Zusatzkosten

Kosten hängen nicht am Feld, sondern am Felderblock. Ein Block kann mehrere Kostenberechnungen haben, und jede Berechnung hat eigene Bedingungen. Deshalb gibt es neben der Feldschleife eine zweite Schleife.

### BPO-Costs

Schleife über die Kostenberechnungen des Blocks. Als Einzel-Tag gibt es deren Anzahl aus.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Data}
   {@BPO-Costs}
      {BPO-Costs_Valid}
         {BPO-Costs_Sum}
            {BPO-Costs_Name}~BPO-Costs_Name~: {/BPO-Costs_Name}
            ~BPO-Costs_Sum~ ~WS-CurrencySymbol~
         {/BPO-Costs_Sum}
      {/BPO-Costs_Valid}
   {/@BPO-Costs}
{/@BPO-Data}
```

### BPO-Costs\_Valid und BPO-Costs\_Sum

`BPO-Costs_Valid` greift, wenn die konfigurierten Bedingungen dieser Kostenberechnung erfüllt sind. `BPO-Costs_Sum` gibt den berechneten Betrag aus und greift als Bereichs-Tag, wenn ein Betrag anfällt.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Costs}
   {BPO-Costs_Sum}
      Aufpreis: ~BPO-Costs_Sum~ ~WS-CurrencySymbol~
   {/BPO-Costs_Sum}

   {!BPO-Costs_Sum}
      keine zusätzlichen Kosten
   {/!BPO-Costs_Sum}
{/@BPO-Costs}
```

> [!WARNING]
>
> Die Kosten fallen an, sobald die Bedingungen der Berechnung erfüllt sind, und nicht erst, wenn der Käufer das Feld ausfüllt. Die einzige Ausnahme ist eine Bedingung, die genau darauf prüft (`Proof = BasketProductOptionInputID` mit `Type = filled`). Eine Kostenberechnung ohne Bedingung schlägt also immer zu, auch bei leerem Feld.

Zeigen Sie die Kosten nur innerhalb von `{BPO-Costs_Valid}` an. Die Schleife läuft über alle konfigurierten Berechnungen, auch über die, deren Bedingungen gerade nicht zutreffen.

### BPO-Costs\_ID, BPO-Costs\_Name und BPO-Costs\_Value

| Tag | Liefert |
| - | - |
| `BPO-Costs_ID` | den eindeutigen Bezeichner der Kostenberechnung |
| `BPO-Costs_Name` | den in der Konfiguration vergebenen Namen |
| `BPO-Costs_Value` | den konfigurierten Rechenwert, also den Betrag oder den Prozentsatz |

> [!WARNING]
>
> `BPO-Costs_Value` ist der Wert aus der Konfiguration, nicht das Ergebnis. Bei `percentualSum` steht dort der Prozentsatz und bei `multiplyWithQuantity` der Betrag je Stück. Was der Käufer zahlt, steht in `BPO-Costs_Sum`.

### Die Art der Berechnung

Drei Bereichs-Tags zeigen an, nach welcher Regel gerechnet wird. Es greift immer genau eines.

| Bereichs-Tag | Bedeutung |
| - | - |
| `BPO-Costs_Type_singleFixCost` | fester Betrag, einmal je (Split-)Position |
| `BPO-Costs_Type_percentualSum` | prozentual zum Warenwert der (Split-)Position beziehungsweise des Warenkorbs |
| `BPO-Costs_Type_multiplyWithQuantity` | Betrag je Stück, multipliziert mit der Menge der (Split-)Position |

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{@BPO-Costs}
   {BPO-Costs_Type_singleFixCost}
      Pauschale von ~BPO-Costs_Value~ ~WS-CurrencySymbol~
   {/BPO-Costs_Type_singleFixCost}

   {BPO-Costs_Type_percentualSum}
      ~BPO-Costs_Value~ % des Warenwerts
   {/BPO-Costs_Type_percentualSum}

   {BPO-Costs_Type_multiplyWithQuantity}
      ~BPO-Costs_Value~ ~WS-CurrencySymbol~ je Stück
   {/BPO-Costs_Type_multiplyWithQuantity}
{/@BPO-Costs}
```

Die drei Tags sind vor allem beim Einrichten nützlich, um zu sehen, welche Regel greift. Dem Käufer gegenüber genügt in aller Regel der fertige Betrag aus `BPO-Costs_Sum`.

### BPO-AllCosts\_Sum

Gibt die Summe aller Zusatzkosten über sämtliche Felderblöcke aus. Als Bereichs-Tag greift es, wenn überhaupt Kosten anfallen.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Aufpreis für freie Felder:
{BPO-AllCosts_Sum}~BPO-AllCosts_Sum~ ~WS-CurrencySymbol~{/BPO-AllCosts_Sum}
{!BPO-AllCosts_Sum}keine{/!BPO-AllCosts_Sum}
```

Dieses Tag steht außerhalb der `BPO-Data`-Schleife und gehört in den Rechnungsfuß neben Versand und Zahlung. Es ist der einzige Wert dieser Gruppe, der die Bestellsumme sichtbar erklärt.

## Die Tags im Überblick

| Tag | Einzel-Tag | Bereichs-Tag | negatives Bereichs-Tag | Schleifen-Tag |
| - | - | - | - | - |
| `BPO-UseOnce` | – | ja | ja | – |
| `BPO-Data` | ja | ja | ja | ja |
| `BPO-LevelOfUsage_Once` | – | ja | ja | – |
| `BPO-LevelOfUsage_BasketPosition` | – | ja | ja | – |
| `BPO-LevelOfUsage_BasketPositionAddress` | – | ja | ja | – |
| `BPO-ID` | ja | – | – | – |
| `BPO-Input` | ja | ja | ja | ja |
| `BPO-Input_ID` | ja | – | – | – |
| `BPO-Input_Type_Input` | – | ja | ja | – |
| `BPO-Input_Type_Checkbox` | – | ja | ja | – |
| `BPO-Input_input` | ja | ja | ja | – |
| `BPO-Input_value` | ja | ja | ja | – |
| `BPO-Input_error` | ja | ja | ja | – |
| `BPO-Input_costs` | ja | ja | ja | – |
| `BPO-Costs` | ja | ja | ja | ja |
| `BPO-Costs_ID` | ja | – | – | – |
| `BPO-Costs_Name` | ja | ja | ja | – |
| `BPO-Costs_Value` | ja | ja | ja | – |
| `BPO-Costs_Type_singleFixCost` | – | ja | ja | – |
| `BPO-Costs_Type_percentualSum` | – | ja | ja | – |
| `BPO-Costs_Type_multiplyWithQuantity` | – | ja | ja | – |
| `BPO-Costs_Sum` | ja | ja | ja | – |
| `BPO-Costs_Valid` | – | ja | ja | – |
| `BPO-AllCosts_Sum` | ja | ja | ja | – |

Zulässig sind die Tags auf der Produktdetailansicht (`ws_product.htm`), der Warenkorbseite (`ws_basket.htm`) und der Bestellübersichtsseite (`ws_place_order.htm`). Mit diesen Ausnahmen:

| Tag | Nur zulässig auf |
| - | - |
| `BPO-UseOnce` | Warenkorbseite |
| `BPO-LevelOfUsage_Once` | Warenkorbseite |
| `BPO-LevelOfUsage_BasketPosition` | Warenkorbseite, Produktdetailansicht |
| `BPO-LevelOfUsage_BasketPositionAddress` | Bestellübersichtsseite |
| `BPO-AllCosts_Sum` | Warenkorbseite, Bestellübersichtsseite |

Alle Tags außer `BPO-UseOnce` und `BPO-AllCosts_Sum` stehen zusätzlich nur innerhalb der `BPO-Data`-Schleife.

## Verwandte Themen

* Wegweiser: Freie Felder auf Split-Positionsebene
* Referenz: Abschnitt `<BasketProductOptions>`
* Referenz: Abschnitt `<GenericInputChecks>`
* Referenz: [BT-BPO\_Refresh](https://dokumentation.websale.de/v8s/referenz/tags/bt/produkt-und-warenkorb.md#schaltflachen-die-anderswo-beschrieben-sind)
* Referenz: [Positionen im Warenkorb](https://dokumentation.websale.de/v8s/referenz/tags/altcurrency.md#positionen-im-warenkorb)


## Related topics

- [Schaltflächen auf Produkt- und Warenkorbseite](https://dokumentation.websale.de/v8s/referenz/tags/bt/produkt-und-warenkorb.md)
- [Freie Eingabefelder im Warenkorb auf Positionsebene](https://dokumentation.websale.de/v8s/warenkorb/freie-eingabefelder-im-warenkorb-auf-positionsebene.md)
- [Warenkorb und Bestellprozess](https://dokumentation.websale.de/v8s/referenz/konfigurationen/shopkonfiguration-shop-config/warenkorb-und-bestellprozess.md)
- [Sektionen: Positionen und Zahlung](https://dokumentation.websale.de/v8s/schnittstellen/bestellungen/ws-bestelldaten/sektionen-positionen-und-zahlung.md)
- [Warenkorb anzeigen und löschen](https://dokumentation.websale.de/v8s/warenkorb/warenkorb-anzeigen-loeschen.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.