This concept describes general aspects regarding promotion validation.
During the checkout all promotion codes in the basket have to be validated. The promotion codes are internally stored as Service Line Items.
The are three checks that have to be executed:
Check | Description |
---|---|
PromotionCodeBO.isActive() | Check if the promotion code and its parents is active (for at least one path - if there are multiple promotions) |
PromotionCodeBO.isAccessible() | Check if the promotion code and its parents is accessible (for at least one path - if there are multiple promotions) |
PromotionCodeBO.canBeRedeemed(UserBO) | Check if the promotion code can be redeemed for the given user (checks number of redemptions total/per user) |
See Concept - Promotion Activation Status and Accessibility for further details about the methods isActive()
and isAccessible()
. The check canBeReemed
will only do checks when
the number of reuses/redemptions total/per user is configured for the promotion or promotion code.
If there are multiple promotions assigned to the same promotion code group, it is sufficient to have one valid promotion.
The following figure shows two examples. In the first example the promotion code is active because there's one path from the root (promotion code) to a leaf (promotion) where all objects are active. In the second example the promotion code and promotion code group are both active, but the assigned promotions or the assigned campaign at the leaf of the tree are not active and as a result the promotion code is not active, too.
A promotion code can be applied to a basket using the BasketBOPromotionCodeExtension
.
As the following example shows the extension provides a method addPromotionCode
which takes a string parameter and returns an AddPromotionCodeResult
.
The result has two methods to determine if the result was successful or not (isFailure
) and which was the reason for failing (getFailureCode
). If the operation was successful the created PromotionCodeBO
can be retrieved from the result via getPromotionCodeBO
.
BasketBOPromotionCodeExtension basketBOPromotionCodeExtension = basketBO.getExtension(BasketBOPromotionCodeExtension.class); AddPromotionCodeResult result = basketBOPromotionCodeExtension.addPromotionCode("INTERSHOP"); if (result.isFailure()) { // do some error handling System.out.println("Error " + result.getFailureCode()); } else { PromotionCodeBO promotionCodeBO = result.getPromotionCodeBO(); // do some further stuff }
The BasketBOPromotionCodeExtension
allows to use an exchangeable PromotionCodeAddToBasketValidator
which is wired via Google Guice. The method validatePromotionCodeAddToBasket
takes the promotion code as String, as well as the BasketBO as parameters. It produces an PromotionCodeAddToBasketValidationResult
. The result contains two methods isFailure
and getFailureCode
.
@Inject private PromotionCodeAddToBasketValidator promotionCodeAddToBasketValidator; ... PromotionCodeAddToBasketValidationResult validationResult = promotionCodeAddToBasketValidator.validatePromotionCodeAddToBasket("INTERSHOP", basketBO); if (validationResult.isFailure()) { // do some error handling System.out.println(validationResult.getFailureCode()); }
The default implementation of the PromotionCodeAddToBasketValidator
validates the given promotion code for:
Check | Description | Error Codes |
---|---|---|
Length | Code must not be null or empty. (maximum length 128 characters) | PromotionCodeEmpty, PromotionCodeMaxLength |
Duplicate | Check whether code is already applied to the basket. | PromotionCodeAlreadyInBasket |
Existence | Check whether promotion code exists in the system. | PromotionCodeNotFound |
Maximum number of codes | Checks the maximum number of promotion codes in the basket (application preference). | NumberOfApplicablePromotionCodesReached |
Activation Status | Check if PromotionCodeBO.isActive() - See Concept - Promotion Activation Status and Accessibility | PromotionCodeNotActive |
Accessibility | Check if PromotionCodeBO.isAccessible() - See Concept - Promotion Activation Status and Accessibility | PromotionCodeNotAccessible |
Redemption check | Check number of redemptions (if configured in the Commerce Management application) | PromotionCodeAlreadyRedeemed |
Promotion applicable | Check if at least one promotion assigned to the code is applicable which checks if the promotion currency matches the basket currency. | NoPromotionApplicable |
For further details how to exchange the validator implementation see Cookbook - Promotion Validation.
Two checkout pipelines provide are the possibility to apply a promotion code: ViewCart-ApplyPromotion
and ViewCheckoutPayment-ApplyPromotion
. The implementations are quite similar and since version 7.9 both use the strict process pipeline ProcessBasket-ApplyPromotionCode
which itself uses the business object layer to redeem a promotion code. The old pipeline which contains a lot of pipeline logic was renamed to ViewCart-ApplyPromotion_Legacy
. For further details about the old implementation and migration see Guide - 7.9 Migration Promotion Validation.
ViewCart-ApplyPromotion
(New since 7.9)
For compatibility reasons the new error codes that are produced by the default implementation of the PromotionCodeAddToBasketValidator
are mapped to the existing error keys that are evaluated in the responsive storefront.
The mapping is defined in a HashMap with Key-Value-Pairs (New Value, Old Value). This is done using the two pipelets AddMultipleEntriesToMap
and the KeyMapper
in the pipeline showed above.
New Error Code from Validator | Existing Error code used in the storefront |
---|---|
PromotionCodeEmpty | not_valid |
PromotionCodeMaxLength | max_length |
PromotionCodeAlreadyInBasket | already_used_in_cart |
PromotionCodeNotFound | not_valid |
NumberOfApplicablePromotionCodesReached | redemptions_reached |
PromotionCodeNotActive | not_valid |
PromotionCodeNotAccessible | not_valid |
PromotionCodeAlreadyRedeemed | redemptions_reached |
NoPromotionApplicable | no_applicable_promotion |
ProcessBasket-ApplyPromotionCode (bc_orderprocess)
The process pipeline ProcessBasket-ApplyPromotionCode
implements the functionality to redeem a promotion code and defines to transaction frame for it. Additionally it provides an extension point where customers can add additional customized functionality after a promotion code has been applied successfully. It can also be used to roll the whole transaction back.
When a promotion code is applied to a basket a reservation entry is created for the code/promotion and basket. The promotion code redemption check which validates the number of left redemptions takes the reservations into account and will treat a valid reservation in the same manner like the code is redeemed in a created order.
If a code is already in the basket and the corresponding reservation is about to expire, the promotion code validation will automatically extend the promotion code reservation if possible (creation date and expiration date are updated). When the maximum number of redemptions is exceeded (either redemptions in orders or only reservations) an error will occur.
For more information see Concept - Promotion Codes - section Reservation of Promotion Codes.