Please note that this documentation is for the most recent version of this extension. It may not be relevant for older versions. Related documentation can be found in the documentation directory of the extension.
Basket-order states (order state machine)
Since version 5.11.0, the shop extension has included an order state machine. This allows you to define the following for each Payment Type / Order Type:
- which states exist,
- which state changes are allowed,
- which changes/states are visible in the backend,
- under which conditions a change is offered.
All flows have in common:
They start with prepared and end with 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 --> [*]
Payment-Type × Order-State 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 | ✔ | – | – | – | – | – | – | ✔ | – | – | ✔ |
Note: The matrix describes typical flows. The actually allowed states are determined via the state machine configuration (see below).
Notes on the Statuses
prepared→ Order is in creation status. No order or invoice number has been assigned yet. Only status in which an order can be deleted in the TYPO3 backend.ordered→ Order has been placed; order and invoice numbers have been assigned.paid→ Payment has been recorded/marked.shipped→ Shipment has been recorded (e.g., shipping date set).requested→ Request has been submitted (request workflow).answered→ Request has been answered/closed (request workflow).credited→ Return/credit note order has been created (negative items) and documented.refunded→ Refund/cancellation document has been created or the refund has been documented (depending on the type).canceled→ The order is unpaid and unshipped and should be canceled. This typically results in a new order of typecancellation(counter-statement/cancellation document).canceled_unpaid→ Cancellation of an order (possible depending on the payment method; often linked to a refund).processed→ The order process is complete (final state for the respective flow).
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 --> [*]
Basic Principle
A state defines the possible subsequent states (transitions). A transition can optionally have a condition. Additionally, a state can be hidden in the backend using a hidden condition.
- allowed: Which target states are reachable from this state?
- condition: When is an allowed transition available?
- hidden: When is a state (or optionally a transition) hidden in the backend?
Important:
- If a state has been reached, only its
allowedtransitions apply. - The state
processedis a final state – however,allowedmust still be defined (empty).
Configuration structure (TypoScript)
The configuration happens in TypoScript:
plugin.tx_shop.settings.basketOrder.orderOptions.<orderType>.status.<state> {
allowed { ... }
hidden { ... }
}
<orderType>is, for example,prePayment,onInvoice,payPal,request,return,storno, …<state>is, for example,prepared,ordered,paid,shipped,processed, …
Example for pre-payment basket-order flow
plugin.tx_shop.settings.basketOrder.orderOptions.prePayment {
status {
prepared {
# In the "prepared" status, the order can only change to "ordered".
allowed {
ordered =
}
}
ordered {
# In the "ordered" status, the order can change to "paid" or "canceled".
allowed {
paid =
canceled =
}
}
paid {
# In the "paid" status, the order can change to "shipped" or "processed".
# The possible states are defined by a condition.
# If multiple conditions are present, they must all be true (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
}
}
# In the status "shipped" the order can only change to "processed".
allowed {
processed =
}
}
canceled {
# In the status "canceled" the order can only change to "processed".
allowed {
processed =
}
}
processed {
# Final state - allowed must exist, but remains empty
allowed =
}
}
}
Reading rule (from the example):
prepared → ordered → paid → shipped → processed
Or (for digital products): paid → processed (without shipping)
Conditions
Conditions control whether a transition (or a complete state) is offered in the backend.
Convention:
- Conditions are structured as "Condition Key → Condition Class" (or resolver).
- A condition is met if the class/logic for the current order evaluates to
true. - Multiple conditions in a block are interpreted as AND.
Conditions:
ContainsDigitalProductsOnlyNotContainsDigitalProductsOnlyNotEmptyEmpty
Typical conditions:
basket = ContainsDigitalProductsOnly: Basket contains only digital productsbasket = NotContainsDigitalProductsOnly: Basket not contains only digital productsbasket = NotEmpty: Basket has itemspaid_date = Empty: Paid date must be emptyordered_date = NotEmpty: Order date must be set
Hide States
A state can be completely hidden in the backend – for example, if a step in the flow is irrelevant for certain orders.
shipped {
hidden {
condition {
basket = ContainsDigitalProductsOnly
}
}
allowed {
processed =
}
}
Result:
- The
shippedstate does not appear for digital-only orders. - The flow can still proceed directly to
processed(via a transition frompaid).
Best Practice: Always Define the End State
Even if processed has no subsequent states, it must exist in the state tree:
processed {
allowed =
}
This ensures the flow is "closed" and the state machine can clearly validate that no further transitions are planned.
Example flows as diagrams
Pre payment basket-order (simplified)
stateDiagram-v2
[*] --> prepared
prepared --> ordered
ordered --> paid
paid --> shipped : physical goods
paid --> processed : digital-only
shipped --> processed
processed --> [*]
Request a basket-order
stateDiagram-v2
[*] --> prepared
prepared --> requested
requested --> answered
answered --> processed
processed --> [*]
Extending the Configuration
You can extend the state machine as needed for each orderOptions.<type>:
- Add new states: Create a state block under
status { ... }. - Add/remove transitions: Adjust
allowed { ... }. - Enforce business rules: Protect transitions with
condition { ... }. - Simplify the UI: Hide irrelevant states using
hidden.condition.
It is important that:
preparedexists as a start state,processedexists as an end state,- Every state has an
allowedblock (even if empty), - No "dead" states exist (states that can never be reached), unless this is intentional.
Typical Pitfalls
- Discounts/Shipping/Taxes do not directly affect the state machine – but your conditions can react to them (e.g., shopping cart contains only digital products).
- State change without a condition means: The change is always available (provided the current state is suitable).
hiddenhides the state, but does not necessarily prevent its existence in the system – it is primarily a UI/backend control.- New order types always require a complete
statusdefinition; otherwise, the flow is unclear.
