Concept - Promotion Validation

1 Introduction

This concept describes general aspects regarding promotion validation.

2 References

3 Promotion Code Validation During Basket Checkout

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:

CheckDescription
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.

PromotionValidation_Principle

4 Promotion Code Validation During Redemption

4.1 Business Object Layer

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.

Example how to use the BasketBOPromotionCodeExtension
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.

PromotionCodeAddToBasketValidator
@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:

CheckDescriptionError Codes
LengthCode must not be null or empty. (maximum length 128 characters)PromotionCodeEmpty, PromotionCodeMaxLength
DuplicateCheck whether code is already applied to the basket.PromotionCodeAlreadyInBasket
ExistenceCheck whether promotion code exists in the system.PromotionCodeNotFound
Maximum number of codesChecks the maximum number of promotion codes in the basket (application preference).NumberOfApplicablePromotionCodesReached
Activation StatusCheck if PromotionCodeBO.isActive() - See Concept - Promotion Activation Status and AccessibilityPromotionCodeNotActive
AccessibilityCheck if PromotionCodeBO.isAccessible() - See Concept - Promotion Activation Status and AccessibilityPromotionCodeNotAccessible
Redemption checkCheck number of redemptions (if configured in the Commerce Management application)PromotionCodeAlreadyRedeemed
Promotion applicableCheck 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.

4.2 Pipeline

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 ValidatorExisting Error code used in the storefront
PromotionCodeEmptynot_valid
PromotionCodeMaxLengthmax_length
PromotionCodeAlreadyInBasketalready_used_in_cart
PromotionCodeNotFoundnot_valid
NumberOfApplicablePromotionCodesReachedredemptions_reached
PromotionCodeNotActivenot_valid
PromotionCodeNotAccessiblenot_valid
PromotionCodeAlreadyRedeemedredemptions_reached
NoPromotionApplicableno_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.

5 Reservation of Promotion Codes

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.

Disclaimer

The information provided in the Knowledge Base may not be applicable to all systems and situations. Intershop Communications will not be liable to any party for any direct or indirect damages resulting from the use of the Customer Support section of the Intershop Corporate Web site, including, without limitation, any lost profits, business interruption, loss of programs or other data on your information handling system.

Customer Support
Knowledge Base
Product Resources
Support Tickets