Info
This concept is valid from Intershop Commerce Mangement 7.10.20.1.
In a B2B scenario, orders may need to be approved by certain users of a customer before they are placed. The order approval workflow can vary in complexity and could also be handled by an external system. To ensure that the order approval is flexible enough, an Order Approval Service is implemented using the Approval Service interfaces from the standard Intershop 7.
The following diagram shows the approval workflow:
The implementation of the service is based on the order approval workflow of the previous version of the B2B Extension Module and supports approval rules as before (see Cookbook - B2B Order Approval for more details).
Currently a generic REST approval callback is not part of the standard implementation. A callback has to be implemented separately when integrating with an external approval system.
With ICM version 7.10.20.1 the approval process which was mainly implemented with pipelines has been re-implemented using customizable handler chains. There are separate handler chains for the Approve and Reject process.
These handler chains are called via a Business Object extension of the BasketBO business object called BasketBOOrderApprovalExtension
.
/** * Starts the approval chain for the extended basket and given approver * @param approver The approver * @return The result of the approval as {@link OrderApprovalResult} */ OrderApprovalResult approve(UserBO approver); /** * Starts the rejection chain for extended basket and given approver * @param approver The approver * @param approvalComment The approval comment * @return The result of the rejection as {@link OrderApprovalResult} */ OrderApprovalResult reject(UserBO approver, String approvalComment);
The return value of the methods calls is an OrderApprovalResult
. It contains the list of possible failures that might have occurred during the approval process. It also contains an optional OrderBO
(only in case of positive approval).
Approve via BasketBOOrderApprovalExtension
:
BasketBOOrderApprovalExtension extension = basketBO.getExtension(BasketBOOrderApprovalExtension.EXTENSION_ID); OrderApprovalResult approvalResult = extension.approve(approver); if (approvalResult.isFailure()) { // error handling } if (approvalResult.getOrderBO().isPresent()) { // approval was the last one -> so order was created OrderBO orderBO = approvalResult.getOrderBO().get(); // ... do further processing }
Reject via BasketBOOrderApprovalExtension
:
BasketBOOrderApprovalExtension extension = basketBO.getExtension(BasketBOOrderApprovalExtension.EXTENSION_ID); OrderApprovalResult approvalResult = extension.reject(approver, "Reject comment..."); if (approvalResult.isFailure()) { // error handling }
The new REST API for requisition approval also uses these BO layer methods for the approval and rejection process.
As mentioned before there are separate handler chains for Approve and Reject. It is possible to visualize the list of registered handler chains by opening the following back office URL manually (adapt host, port to your local environment):
https://<host:port>/INTERSHOP/web/WFS/inSPIRED-Site/en_US/-/USD/InspectHandlerChains-Start
The two chains will be explained in detail in the following sections.
The OrderApprovalApproveChain
which handles the positive case Approve consists of two sub-chains: A PreOrderApprovalApproveChain
and the OrderApprovalApproveChain
itsself.
The PreOrderApprovalApproveChain
does some general checks before the approval process can start, e.g., if the approval feature is generally enabled or the requisition (basket) has to be approved by the user. If any of the checks fails, the execution of the whole handler chain will be stopped (Stop On Failure).
The OrderApprovalApproveChain
contains all necessary steps for an approval like adjusting the approval steps, setting the basket status, creating emails etc. If any of the handlers fails, the process will be continued anyway (Continue On Failure).
The OrderApprovaRejectChain
which handles the negative case Reject also consists of two sub-chains: A PreOrderApprovalRejectChain
and the OrderApprovalRejectChain
itsself.
Again the PreOrderApprovalRejectChain
does some general checks before the approval process can start, e.g. if the approval feature is generally enabled or the requisition (basket) has to be approved by the user. If any of the checks will fail, the execution of the whole handler chain will be stopped (Stop On Failure).
The OrderApprovalRejectChain
contains all necessary steps for an approval reject like adjusting the approval steps, setting the basket status, creating emails etc. If any of the handlers fails, the process will be continued anyway (Continue On Failure).
The following diagram describes the main classes used by the Intershop Commerce Management approval service implementation. For more information on the approval service itself, refer to Concept - Approval Managed Service.
ApprovalRequiredRule
- A rule that can determine whether approval is required for a given buyer and requisition. For example a rule could say approval is required if the requisition total is greater than the buyer's budget. In general the rules should perform simple checks.ApprovalRequiredRuleProvider
- A provider for ApprovalRequiredRule
instances.ApprovalStepBO
- A unit that needs to be approved by a single approver. Multiple steps can be associated with the same requisition. In general each step of the same requisition should require approval by a different set of users (e.g., any of the users with the permission to approve orders, the manager of a cost center, etc.). Different ApprovalRequiredRule
instances could require different approval steps. Once all applicable approval steps for a requisition are set to approved, then the requisition is considered as approved and the order creation process could start. If any of the approval steps for a requisition is set to Rejected, then the entire requisition is considered to be refused. In case the same user is responsible for more than one approval step of a requisition, he could set the approval decision for all steps in one action(Approve or Reject).BusinessObjectApprovalStepExtension
- Manages the approval steps. It is also aware of which steps need to be created for a requisition based on the ApprovalRequiredRule
instances.EligibleApproverPredicate
- A predicate that can be used to determine whether a user is eligible to approve an approval step. For example a predicate could check whether the user has the permission to approve orders. The predicate is used internally by the default implementation of the approval step BO.The ApprovalRequiredRule
and EligibleApproverPredicate
are available as contract components and can be used to add new rules or trigger the creation of new steps. For more details refer to Cookbook - B2B Order Approval.
The following rules are available and wired out of the box:
BudgetThresholdApprovalRule
- requires approval if the requisition total exceeds the buyer's budget. Applicable for one time purchase baskets, but not for baskets automatically created from approved subscription.SingleOrderThresholdApprovalRule
- requires approval if the requisition total exceeds the buyer's limit for a single order. Applicable for one time purchase baskets, but not for baskets automatically created from an approved subscription.CostCenterApprovalRule
- requires approval if the requisition is assigned to a cost center. In case the buyer is assigned as buyer for at least one cost center, a cost center must be selected and it is assigned to the basket. Once the basket has cost center assigned it requires approval, unless it is automatically created from approved subscription.SubscriptionApprovalRule
- requires approval if the requisition is a subscription. Once the subscription is approved, all subsequent baskets created from it are also considered as automatically approved.The following predicates are available and wired out of the box:
ApprovalPermissionEligibleApproverPredicate
- users with the permission to approve orders can approve a step. This is set as default. Steps are created using this predicate when a rule does not have a specific assignment.CostCenterEligibleApproverPredicate
- the manager of the cost center to which the requisition is assigned. A step using this predicate is created if approval is required by the CostCenterApprovalRule
.The following diagram illustrates possible basket state changes related to the approval process:
BASKET_OPEN
- Basket is open for every kind of manipulation, such as adding products, warranties and coupons or removing line items.BASKET_ORDERED
- Checkout of basket has been successfully finished.One time purchase requisitions has basket type REQUISITION(10)
. Subscriptions has basket type RECURRINGBASKET(11)
. Before to start the Checkout process it is possible to switch basket type from REQUISITION
to RECURRINGBASKET
and vise versa.