Order Hold Strategies
Overview
Order Hold Strategies provides a mechanism for adding logic that determines whether an order is placed on hold during the final cart checkout process. Inventory and payment reservations must process before any holds are placed. The framework supports multiple holds on each order, and all holds must be resolved before the order is released for capture and fulfillment. Holds can be marked resolved or unresolvable by business users within Commerce Manager. If any holds are marked unresolvable, the order is cancelled.
You can use this feature to implement several use cases, such as:
- Provide a holding queue for the authorization or capture of payment methods that are not real-time, such as cheque or purchase order.
- Provide a way to inject a review, manual or automated, process into the order capture process. For example, fraud review, promotion applicability, and so on.
- Provide a way to delay the computationally expensive process of transferring orders to fulfillment during peak traffic windows.
Usage
By default, Elastic Path ships with one order hold strategy, Hold All Orders. This strategy holds all orders at checkout if the COMMERCE/SYSTEM/ONHOLD/holdAllOrdersForStore
setting is set to true
. You can also set context values for each store to only hold orders for certain stores.
When you enable this setting and a shopper checks out, an order is created in the On Hold state. The shopper receives an order confirmation email. Payment will not be captured and the order is not sent to fulfillment.
Assuming that this setting is enabled, when a shopper checks out, an order will be created in the On Hold state, and they will receive an Order Confirmation email. However, payment will not be captured and the order will not be sent to fulfilment.
Every four hours, or as configured in COMMERCE/SYSTEM/ONHOLD/holdNotificationInterval
, the batch server checks for orders in the On Hold state. If any orders are found, an email is sent to the business user email configured in COMMERCE/SYSTEM/ONHOLD/holdNotificationRecipientEmail
. The email indicates the number of held orders are ready for review.
The business user can sign in to Commerce Manager, search for On Hold` orders, and can mark the holds as resolved or unresolvable. For more information, see Customer Service Order Holds.
note
The business user is only permitted to mark holds as resolved or unresolvable if they have the required permission specified by the order hold strategy. For the "Hold All Orders" strategy, this is configured in COMMERCE/SYSTEM/ONHOLD/holdAllOrdersForStoreResolvePermission
and set to RESOLVE_GENERIC_HOLD
by default.
If all holds are resolved, the order switches to the IN_PROGRESS
state. If applicable, payment is captured, and the order will be sent to fulfillment. If all shipments are electronic, then the order will switch to the COMPLETED
state.
If any holds are marked unresolvable, the order switches to the CANCELLED
state, payment and inventory reservations will be reversed, and the shopper will receive a cancellation email.
Checkout Processing with Order Hold Strategies
When a cart is checked-out using the Cortex purchaseform
, a set of checkout actions are executed. These checkout actions execute a series of steps to convert the cart into an order, collect payment, update inventory, and so on.
As shown in the following diagram, several checkout actions are executed before the hold strategies are evaluated. This ensures that actions such as payment and inventory reservation are completed before holding the order.
note
Only a subset of all checkout actions are shown in the preceding diagram.
If one or more order hold strategies indicates that the order needs to be held, the order status is changed to
ONHOLD
and anORDER_HELD
event message is published. Currently, there are no listeners for this event message, but it could be used by an extension.When a business user marks a hold as resolved or unresolvable, Commerce Manager publishes an
ORDER_HOLD_UPDATED
event. Integration Server listens for this event and updates the hold to the correct state. If the hold was marked asUNRESOLVABLE
, the order is cancelled. If the hold was marked asRESOLVED
, and all other holds have been resolved, then anORDER_ACCEPTED
message is published.If the order hold strategies don’t indicate that the order needs to be held, or if all order holds are resolved, an
ORDER_ACCEPTED
event message is published. Integration Server listens for this event and processes the checkout actions listed inreversiblePostHoldResolvedCaptureActions
. This captures payment and sends the order to fulfillment, amongst other actions.
Creating Custom Order Hold Strategies
Follow these steps to create a custom order hold strategy:
Create a class in
ext-core
that implementsOrderHoldStrategy
.Implement the one method required by that interface:
Optional<OrderHold> evaluate(PreCaptureCheckoutActionContext context);
The
PreCaptureCheckoutActionContext
parameter contains details about the request, such as the shopping cart, shopper, and a shopping cart pricing snapshot. These can be used by the strategy to make decisions about whether the order should be held.If the strategy determines that the order should be held, it should create and return an
OrderHold
object shown in the following example:final OrderHold orderHold = beanFactory.getPrototypeBean(ContextIdNames.ORDER_HOLD, OrderHold.class); orderHold.setStatus(OrderHoldStatus.ACTIVE); orderHold.setHoldDescription("Custom hold description."); orderHold.setPermission("RESOLVE_GENERIC_HOLD"); return orderHold;
Create a bean definition for the class in the
ep-core-plugin.xml
file, shown in the following example:<bean id="customOrderHoldStrategy" class="com.elasticpath.extensions.service.shoppingcart.holdstrategies.CustomOrderHoldStrategyImpl"> <property name="beanFactory" ref="coreBeanFactory"/> </bean>
Add the custom order hold strategy to the
orderHoldStrategyList
list in the same file, as shown in the following example:<extensibleList:modify id="orderHoldStrategyList" parent="orderHoldStrategyListParent"> <extensibleList:addToList> <ref bean="customOrderHoldStrategy"/> </extensibleList:addToList> </extensibleList:modify>