Introduction
The previous lecture outlined the configuration of contract logics, so that end-users could set up promotions. When a contract was approved, a price record was created out of every contract line item.
This lecture explores how to take these promotions — stored as price records — and apply them to products. The principle is the same whether it means applying promotions to quote line items, or analyzing promotions in dashboards.
This lecture will primarily focus on the use of promotions in Quoting, as it is the most common usage.
Lab Disclaimer: Although this lab offers comprehensive information on the mentioned capability, it lacks a Pricefx environment, that is only available in our instructor-led training, where you can interact with these features and practice using them.
For further insights into the distinctions between our on-demand learning paths and instructor-led training, please click here.
Labs in this section require a specific training partition to complete. To request your training partition please write a request on this email: maros.grman@pricefx.com.
The partition request can take a few days to be processed, once the verification is finished you will receive the credentials by email.
Promotions in the Quoting
When an end-user — typically a sales representative — create a quote in the Quoting, he/she may not be aware of
promotions that targets the customer.
promotions that targets the products.
As such, any eventual promotions that were set up in the PromotionManager must be applied automatically to the quote. This means that the quote logic should be designated at least one output element for promotions.
The problem can be broken down into two parts:
Find the promotions that applies to the quote line item.
Calculate the discount — based on the parameters in the contract.
The second part is trivial in the special case where the promotion is a simple discount. Therefore, this part will be left out of this document, but will be covered in the laboratory exercise.
Finding Promotions
The first challenge is to find the promotions that applies to a given product. The quote logic will be querying the Price Records table, and as such, rely on the fact that the price records stores all the conditions that were set up on the contract line item. Common conditions are
Validity
The time period during which the promotion is valid. Stored in the (price record) fields validAfter
and expiryDate
.
Customer group
A set of customers that can benefit from the promotion. Technically, it is a filter for the Customer Master table. Stored in the (price record) field customerGroup
.
Product group
A set of products for which the promotion applies. Stored in the (price record) field productGroup
.
With the conditions in mind, a filter for price records will be constructed and supplied as an argument to api.stream()
.
api.stream("PR", null, null, *filters)
The filter on the validity is trivial:
def filters = [] filters << Filter.lessOrEqual("validAfter", api.targetDate()) filters << Filter.greaterOrEqual("expiryDate", api.targetDate())
remember, in Quote Logic, the TargetDate represents the Effective Date of the Quote document |
For the filter on the product and customer groups, there are a couple of functions that helps create the filters: [1] [2]
Example 1. These functions helps create the filters for the product and customer groups.
filters << api.productToRelatedObjectsFilter('PR', productId) filters << api.customerToRelatedObjectsFilter('PR', customerId)
As arguments, these functions takes the type code of the table the filter is going to be used with, and the identifier of the object being matched against the price records. The price record contains two fields, productGroup
and customerGroup
, each of which holds a filter. This filter is going to be matched against the identifier in the second argument.
However, if the end-user who set up the filter didn’t specify a value for the product/customer group, the value of productGroup
/customerGroup
in the price record will be null
and therefore not match against the filter in Example 1. The solution to this is to match null
(in the price record) against all values of the product/customer identifier:
Example 2. The or
condition ensures that left-out values for the productGroup
and customerGroup
fields means that the promotion applies to all products and customers.
filters << Filter.or( api.productToRelatedObjectsFilter("PR", out.ProductId), Filter.isNull("productGroup") ) filters << Filter.or( api.customerToRelatedObjectsFilter("PR", out.CustomerId), Filter.isNull("customerGroup") )
If the end-users are allowed to leave the input for customer group or product group blank, the filter in Example 2 must be used in the quote logic. Otherwise, the promotion will not be applicable to any products or customers.
The same type of filter can be used in other contexts, such as in dashboards — to find the promotions related to specific products and customers.
Summary
To apply promotions to quote line items, query the Price Record table. As an argument, provide a list of filters to find the applicable promotions. Common filters are
Validity
Customer group
Product group
Where the customer and/or product groups optional inputs to the promotions, include the following filters:
filters << Filter.or( api.productToRelatedObjectsFilter("PR", productId), Filter.isNull("productGroup") ) filters << Filter.or( api.customerToRelatedObjectsFilter("PR", customerId), Filter.isNull("customerGroup") )
References
Developer Documentation
Documentation (Classic)
Older Training Materials
Accelerators (non-public)
1. https://qa.pricefx.eu/pricefx-api/groovy/master/net/pricefx/formulaengine/scripting/PublicGroovyAPI.html#productToRelatedObjectsFilter(java.lang.String,java.lang.String)^
2. https://qa.pricefx.eu/pricefx-api/groovy/master/net/pricefx/formulaengine/scripting/PublicGroovyAPI.html#customerToRelatedObjectsFilter(java.lang.String,java.lang.String)^