How to Set Up a Buy-One-Get-One-Free Promotion

Business use case:

You want to create a promotional campaign, in which your customers, when they buy a specified product, receive a free bonus product. In practice, this means that after adding a certain product to a quote, another product is added automatically with a zero price tag.

Requirements:

  • After choosing a customer and adding product X to the quote, product Y should be added to the quote automatically.

  • After changing the quantity of product X and clicking 'Recalculate Changes' or 'Recalculate', the quantity of product Y should change accordingly and the user input should be read-only.

  • The 'Requested Price' input should be set to 0 and read-only for product Y.

  • After deleting a quote line containing product X  and clicking 'Recalculate Changes' or 'Recalculate', the line with product Y should be deleted.

Solution:

The solution will consist of two parts. First, we define the promotion in Agreements & Promotions and in the second part, we will handle the promotion in the quote.

Agreements & Promotions

First of all we need to create a logic for the promotion. The logic will enable us, when creating a new document, to determine which products will be promoted, to which customer groups it will apply and set the priority in case that we create more promotions.

Its conditions will be stored in Price Records, and for this reason, the PR column names must be the same as the names of the elements in the promotion calculation logic. We need to store the following information: ContractTermType, PromotionalProduct, PromotionPriority (change the names of PR columns accordingly). In this example we use the following names: PromotionPriority-attribute1, ContractTermType-attribute5, PromotionalProduct-attribute6.

In Administration > Logics > Agreements & Promotions, we create the promotion logic, which will consist of five elements.

The first element creates a user input where the promoted product is selected:

ProductGroup.groovy
def pg =api.productGroupEntry() if(pg!=null && !"sku".equals(pg?.productFieldName)){ api.redAlert("Only one product is permitted!") } return pg?.productFieldValue

The second element creates a user input for selecting the free promotional product:

PromotionalProduct.groovy
def pg =api.productGroupEntry("Promotional Product") if(pg!=null && !"sku".equals(pg?.productFieldName)){ api.redAlert("Only one product is permitted!") } return pg?.productFieldValue

The third element creates a user input for Customer Group:

CustomerGroup.groovy
def cg =api.customerGroupEntry() return cg

The fourth element creates a user input for assigning a priority level to the promotion:

PromotionPriority.groovy

And finally the fifth element saves the information about Condition Type to the Price Records:

ContractTermType.groovy

When we have all the information about our promotion safely stored in Price Records, we can use it in Quotes.

Quoting

To achieve the functionality described at the beginning of this article, we need to transport information from the quote header logic (that adds the bonus item) to the line logic. We will use HIDDEN type inputs to do that (see also How to Create Quote Line Items from Header Logic).

First, we will create a quote header logic:

Then we need to create a logic for the quote line items in Administration > Logics > Generic Logic. This logic will have three elements.

The first element creates a user input, where the user indicates the desired quantity of the product:

The second element creates a user input, where the user indicates the requested price:

In the third element, we just want you to show, that in the line logic we can read a value of the input which has been added in Header Logic.

Every time you add product X to your quote, the header and line logics will be executed in the following order:

  1. Header logic in the pre-phase.

  2. Line logic for new product (X).

  3. Line logic for the new, added by the header logic, product (Y).

  4. Header logic in the post-phase.

For your convenience, all the code samples are downloadable below:

Found an issue in documentation? Write to us.