Bitte beachte, dass sich diese Dokumentation auf die neuste Version dieser Erweiterung bezieht. Wenn eine ältere Version eingesetzt wird, kann diese abweichen. Die jeweils passende Dokumentation befindet sich im Dokumentation-Verzeichnis der Erweiterung.
Bestell-Zustandsautomat (order state machine)
Seit Version 5.11.0 hat die Shop-Erweiterung einen Bestell-Zustandsautomaten („state-machine“). Damit definierst Du pro Payment-Type / Order-Type:
- welche States es gibt,
- welche State-Wechsel erlaubt sind,
- welche Wechsel/States im Backend sichtbar sind,
- unter welchen Bedingungen ein Wechsel angeboten wird (Conditions).
Gemeinsamkeit aller Flows:Sie starten mit prepared und enden mit processed.
stateDiagram-v2
[*] --> prepared : Order is being prepared (FE customer / BE operator)
prepared --> customSteps : Order placed (order + invoice no. assigned)
customSteps --> processed : Order is finished
processed --> [*]
Bezahlart × Bestell-Status Matrix
| Payment-Type | prepared | ordered | paid | shipped | requested | answered | credited | refunded | canceled | canceled_unpaid | processed |
|---|---|---|---|---|---|---|---|---|---|---|---|
| request (Produkt-Anfrage) | ✔ | – | – | – | ✔ | ✔ | – | – | – | – | ✔ |
| onInvoice (Rechnung) | ✔ | ✔ | ✔ | ✔ | – | – | – | – | – | ✔ | ✔ |
| prePayment (Vorkasse) | ✔ | ✔ | ✔ | ✔ | – | – | – | – | – | ✔ | ✔ |
| sepa (SEPA-Lastschrift) | ✔ | ✔ | ✔ | ✔ | – | – | – | – | – | ✔ | ✔ |
| payPal (PayPal-Wallet) | ✔ | ✔ | ✔ | ✔ | – | – | – | – | ✔ | ✔ | ✔ |
| payPalCheckout | ✔ | ✔ | ✔ | ✔ | – | – | – | – | – | ✔ | ✔ |
| stripe (Kreditkarte etc.) | ✔ | ✔ | ✔ | ✔ | – | – | – | – | – | ✔ | ✔ |
| klarna | ✔ | ✔ | ✔ | ✔ | – | – | – | – | – | ✔ | ✔ |
| manual (manuelle Bestellung) | ✔ | ✔ | ✔ | ✔ | – | – | – | – | – | ✔ | ✔ |
| Return (Retoure) | ✔ | – | – | – | – | – | ✔ | ✔ | – | – | ✔ |
| Storno | ✔ | – | – | – | – | – | – | ✔ | – | – | ✔ |
Hinweis: Die Matrix beschreibt typische Flüsse. Die tatsächlich erlaubten States werden über die State-Machine-Konfiguration bestimmt (siehe unten).
Hinweise zu den Zuständen
prepared→ Bestellung ist in einem Erstellungsstatus. Es wurde noch keine Bestell- oder Rechnungsnummer vergeben. Einziger Status, in dem eine Bestellung im TYPO3-Backend gelöscht werden kann.ordered→ Bestellung wurde platziert; Bestell- und Rechnungsnummer wurden vergeben.paid→ Zahlung wurde verbucht/markiert.shipped→ Versand wurde erfasst (z. B. Versanddatum gesetzt).requested→ Anfrage wurde gestellt (Anfrage-Workflow).answered→ Anfrage wurde beantwortet/abgeschlossen (Anfrage-Workflow).credited→ Retoure-/Gutschrift-Bestellung wurde erstellt (negative Positionen) und dokumentiert.refunded→ Erstattung/Storno-Dokument wurde erstellt bzw. Erstattung wurde dokumentiert (je nach Typ).canceled→ Bestellung ist nicht bezahlt und nicht versandt und soll storniert werden. Daraus resultiert typischerweise eine neue Bestellung vom Typstorno(Gegendarstellungs-/Storno-Dokument).canceled_unpaid→ Abbruch einer Bestellung (je nach Zahlungsart möglich; oft mit Geldfluss/Refund gekoppelt).processed→ Bestellvorgang ist abgeschlossen (Endzustand für den jeweiligen Flow).
Grundprinzip
Ein State definiert die möglichen Folgestates (Transitions). Eine Transition kann optional eine Condition haben. Zusätzlich kann ein State per hidden-condition im Backend ausgeblendet werden.
- allowed: Welche Ziel-States sind aus diesem State heraus erreichbar?
- condition: Wann ist ein allowed-Übergang verfügbar?
- hidden: Wann ist ein State (oder optional auch ein Übergang) im Backend ausgeblendet?
Wichtig:
- Wenn ein State erreicht wurde, gelten ausschließlich dessen
allowed-Transitions. - Der State
processedist ein Endzustand – trotzdem mussalloweddefiniert sein (leer).
Konfigurationsstruktur (TypoScript)
Die Konfiguration erfolgt in TypoScript unter:
plugin.tx_shop.settings.basketOrder.orderOptions.<orderType>.status.<state> {
allowed { ... }
hidden { ... }
}
<orderType>ist z. B.prePayment,onInvoice,payPal,request,return,storno, …<state>ist z. B.prepared,ordered,paid,shipped,processed, …
Beispiel: prePayment (Vorkasse)
plugin.tx_shop.settings.basketOrder.orderOptions.prePayment {
status {
prepared {
# Im status "prepared" kann die Bestellung nur zu "ordered" wechseln.
allowed {
ordered =
}
}
ordered {
# Im status "ordered" kann die Bestellung zu "paid" oder "canceled" wechseln.
allowed {
paid =
canceled =
}
}
paid {
# Im status "paid" kann die Bestellung zu "shipped" oder "processed" wechseln.
# Die möglichen States sind mit einer Condition belegt.
# Wenn mehrere Conditions enthalten sind, müssen diese alle zutreffen (AND).
allowed {
shipped {
# Show marked-as-shipped when not "only digital products" are in basket-order
condition {
basket = NotContainsDigitalProductsOnly
}
}
processed {
# Skip shipping step for digital-only orders
condition {
basket = ContainsDigitalProductsOnly
}
}
}
}
shipped {
# Hide whole shipped state when "only digital products" are in basket-order
hidden {
condition {
basket = ContainsDigitalProductsOnly
}
}
# Im status "shipped" kann die Bestellung nur zu "processed" wechseln.
allowed {
processed =
}
}
canceled {
# Im status "canceled" kann die Bestellung nur zu "processed" wechseln.
allowed {
processed =
}
}
processed {
# Endzustand – allowed muss existieren, bleibt aber leer
allowed =
}
}
}
Leseregel (aus dem Beispiel):
prepared → ordered → paid → shipped → processed
Oder (bei digitalen Produkten): paid → processed (ohne Versand)
Conditions
Conditions steuern, ob eine Transition (oder ein kompletter State) im Backend angeboten wird.
Konvention:
- Conditions sind als „Condition-Key → Condition-Klasse“ (oder Resolver) aufgebaut.
- Eine Condition wird erfüllt, wenn die Klasse/Logik für die aktuelle Bestellung
trueergibt. - Mehrere Conditions in einem Block werden als AND interpretiert.
Conditions:
ContainsDigitalProductsOnlyNotContainsDigitalProductsOnlyNotEmptyEmpty
Typische Conditions:
basket = ContainsDigitalProductsOnly: Warenkorb enthält nur digitale Produktebasket = NotContainsDigitalProductsOnly: Warenkorb enthält nicht nur digitale Produktebasket = NotEmpty: Warenkorb muss nicht leer seinpaid_date = Empty: Bezahlungsdatum muss leer seinordered_date = NotEmpty: Bestelldatum muss gesetzt sein
States ausblenden (hidden)
Ein State kann komplett im Backend ausgeblendet werden – z. B. wenn ein Schritt im Flow für bestimmte Bestellungen irrelevant ist.
shipped {
hidden {
condition {
basket = ContainsDigitalProductsOnly
}
}
allowed {
processed =
}
}
Ergebnis:
- Der State
shippedtaucht für digitale-only Bestellungen nicht auf. - Der Flow kann trotzdem direkt nach
processedführen (über Transition auspaid).
Best-Practice: Endzustand immer definieren
Auch wenn processed keine Folgestates hat, muss es im Statusbaum existieren:
processed {
allowed =
}
So ist der Flow „geschlossen“ und die State-Machine kann eindeutig validieren, dass keine weiteren Übergänge vorgesehen sind.
Beispiel-Flows als Diagramm
Vorauskasse Bestellung
stateDiagram-v2
[*] --> prepared
prepared --> ordered
ordered --> paid
paid --> shipped : physical goods
paid --> processed : digital-only
shipped --> processed
processed --> [*]
Anfrage Bestellung
stateDiagram-v2
[*] --> prepared
prepared --> requested
requested --> answered
answered --> processed
processed --> [*]
Konfiguration erweitern
Du kannst die State-Machine pro orderOptions.<type> beliebig erweitern:
- Neue States hinzufügen: State-Block unter
status { ... }anlegen. - Übergänge hinzufügen/entfernen:
allowed { ... }anpassen. - Business-Regeln erzwingen: Transitions mit
condition { ... }schützen. - UI vereinfachen: irrelevante States per
hidden.conditionausblenden.
Wichtig ist, dass:
preparedals Start-Status existiert,processedals End-Status existiert,- jeder State einen
allowed-Block besitzt (auch wenn leer), - keine „toten“ States existieren (States, die nie erreicht werden können), sofern das nicht bewusst so gewollt ist.
Typische Stolperfallen
- Rabatte/Versand/Steuern* beeinflussen nicht die State-Machine direkt – aber Deine Conditions können darauf reagieren (z. B. Warenkorb enthält nur digitale Produkte).
- State-Wechsel ohne Condition bedeutet: Der Wechsel ist immer verfügbar (sofern der aktuelle State passt).
hiddenblendet aus, verhindert aber nicht zwingend die Existenz eines States im System – es ist primär UI/Backend-Steuerung.- Neue Order-Types benötigen immer eine vollständige
status-Definition, sonst ist der Flow unklar.
