Info |
---|
This guide is for Strategy Designer version 1.0.0 released as part of the Paper Plane release on July 25th, 2023. |
Strategy Designer is a visual interface for configuring selected aspects of the Accelerate Price Setting Package (PSP) which it also depends on.
The main focus of Strategy Designer is to allow business users to configure custom strategies that would otherwise need to be coded in Groovy. Strategy Designer provides visual experience powered by Google Blockly technology (open source).
The main features of Strategy Designer are:
Feature | Configures the following part of PSP |
---|---|
Design custom strategies using a drag & drop interface. | |
Assign strategies to different product segments and set each strategy’s importance. | |
Preview each strategy’s result in a Live Preview panel. | PSP does not have this feature. |
Deploy the strategies and the importance settings to the partition. |
Warning |
---|
What Strategy Designer is not:
|
Deploy to the Partition
...
Once you are satisfied with the strategies and their prioritization, you can deploy everything to the partition by clicking on the Deploy button. A confirmation dialog will appear and after confirming, you will be taken to the Deploy screen which will give you information about the deployment progress.
...
If no error was encountered, you will be presented with the success message and a button that will take you back to the first step while reloading all the data from the freshly updated partition.
If an error was encountered, it means the deployment was unsuccessful. This can happen mainly because of a wrong configuration of the Price Setting Accelerator. In case you encounter an error, write down the error message and send it to the support team.
How the configuration is stored
There are two kinds of configuration stored on the partition, the deployed and the draft. When you open the Strategy Designer, it will look if there is a draft version available on the partition and if it is, it will load it. If not, it will load the last deployed configuration, if present.
A user can always discard his draft and load the last deployed configuration from the partition. This is done from the three-dot menu in the top-right corner.
...
Each time you make a change to the configuration (list of strategies, lookups, blocks), it is automatically saved to the partition as a draft. There is one draft per user, which means that each user can have his own work-in-progress version of the strategies. You can see the status of your configuration in the status bar in the app’s header.
...
There is, however, just one deployed configuration stored on the partition. This means that whenever a user deploys his draft to the partition, it will overwrite the previous version of the deployed configuration. And this new configuration will be then available to the other users, who would be able to load it (either by discarding their draft or automatically, if the user didn’t have any draft).
Info |
---|
Until you deploy your configuration, you’re playing in your own playground. When you deploy the configuration, it will become visible and active for PSP and available to other users of the Strategy Designer, who would be able to load it. |
Advanced Configuration
Note |
---|
This section is for advanced users only. An error in the configuration will result in the Strategy Designer not loading correctly or not loading at all. You have been warned! |
Deployment and Installation
The Strategy Designer is deployed as part of the Price Setting Package from the Pricefx Platform Marketplace. This is the preferred way because it also creates the necessary business role.
If you’re deploying it manually, make sure you have the Price Setting Package version 2.1.3 or newer installed on your partition.
Manual deployment
To manually deploy the Strategy Designer, follow these instructions:
Go to Configuration > Advanced Configuration Options
Create a new entry named
pfxExternalApp_visual_configuration_strategy_designer
The important part is the prefixpfxExternalApp_
, the rest is up to you.Copy & paste the following JSON as the entry’s Value:
Code Block { "name": "strategy-designer", "label": "Strategy Designer", "url": "https://apps.pricefx.com/visual-configuration/1-0-0/#/strategy-designer", "businessRole": "StrategyDesigner", "configuration": { } }
This creates a default configuration for the Strategy Designer. It can be further adjusted via the configuration options
...
Master Data > Administer Company Parameters
Price Setting > Manage Calculation Logics
Price Setting > View LPG
Price Setting > View Price Lists
Administration > Data Integration
5. Assign this business role to the users who should be able to use the Strategy Designer
6. Refresh your browser
After these steps, the Strategy Designer should appear in the main menu under External Applications.
Note |
---|
Make sure your JSON is syntactically correct. No trailing commas are allowed. |
Warning |
---|
The StrategyDesigner role will give the users access to certain Pricefx features, which they otherwise might not have access to. This is the current limitation. Be careful who you give access to. |
...
Currently, the only way to upgrade your existing Strategy Designer configuration is to manually update the url
parameter in the Advanced Configuration Options.
Go to Configuration > Advanced Configuration Options
Open the entry with your Strategy Designer configuration. It will start with pfxExternalApp_, like
pfxExternalApp_visual_configuration_strategy_designer
.Update the
url
parameter to point to the new version:
The Strategy Designer is deployed athttps://apps.pricefx.com/visual-configuration/{VERSION}/#/strategy-designer
where{VERSION}
is the released version’s number with dashes instead of dots.
For example, version 1.0.0 is at URLhttps://apps.pricefx.com/visual-configuration/1-0-0/#/strategy-designer
Save the entry
Refresh your browser
After updating the URL and saving the entry, refresh your browser and open the Strategy Designer again from the External Applications in the main menu.
...
The Strategy Designer’s additional configuration is stored in its configuration
JSON in the pfxExternalApp_visual_configuration_strategy_designer
entry in the Advanced Configuration Options. The value is a JSON object.
A default configuration looks like this:
Code Block | ||
---|---|---|
| ||
{
"name": "strategy-designer",
"label": "Strategy Designer",
"url": "https://apps.pricefx.com/visual-configuration/1-0-0/#/strategy-designer",
"businessRole": "StrategyDesigner",
"configuration": {
"advancedConfigurationStateEntry": "visual_configuration_psp_state",
"stateLookupTableName": "StrategyDesignerState",
"dependencyConfigurationTable": "DependencyConfiguration",
"priceListLogicName": "IndependentPriceListLogic",
"priceSettingDimensionsTable": "PriceSettingDimensions",
"strategyDefinitionTable": "StrategyDefinition",
"livePreviewDependencyLevel": "Global",
"groovyLibraryName": "CustomPricingStrategiesLib",
"customBlocksGroovyLibraryName": "StrategyDesignerCustomBlocks",
"excludedParameters": [],
"additionalParameters": {}
}
}
|
You can only specify the parameters you want to change. Others will use their default values.
The name, label, url, and businessRole are needed for Unity in order to display the Strategy Designer in the menu.
name is a unique name among the external applications which will be part of the URL. Make sure it’s unique among all
pfxExternalApp_
entrieslabel is the text of the menu item. You can safely change this
url is the URL pointing to the server where the Strategy Designer is deployed
businessRole is the business role the user has to have assigned to see the menu item
configuration is an application-specific configuration, in our case it contains the configuration options for the Strategy Designer
Following is a list of options you can specify within the configuration object, with their default values and a description. A default value is used when you omit the option.
...
Option
...
Default Value
...
Description
...
advancedConfigurationStateEntry
...
“visual_configuration_psp_state”
...
A key in the Advanced Configuration Options where the deployed state of the Strategy Designer is stored. Change this if you want the Strategy Designer to store its deployed state elsewhere, or load it from elsewhere.
...
stateLookupTableName
...
“StrategyDesignerState”
...
A company parameter where the draft state of the Strategy Designer is stored
...
dependencyConfigurationTable
...
“DependencyConfiguration”
...
PSP table where dependencies are configured. Unless you have a custom PSP deployment, you should not need to change this.
...
priceListLogicName
...
“IndependentPriceListLogic”
...
The name of the PSP’s IndependentPriceListLogic. Unless you have a custom PSP deployment, you should not need to change this.
...
priceSettingDimensionsTable
...
“PriceSettingDimensions”
...
PSP table where dimensions are configured. Unless you have a custom PSP deployment, you should not need to change this.
...
strategyDefinitionTable
...
“StrategyDefinition”
...
PSP table where strategy definitions are configured. Unless you have a custom PSP deployment, you should not need to change this.
This is where the custom strategies are written when they’re deployed.
...
livePreviewDependencyLevel
Status | ||
---|---|---|
|
...
“Global”
...
The default dependency level for the Live Preview. It has become obsolete in version 1.0.0 where you can pick the level yourself from a drop-down.
...
groovyLibraryName
...
“CustomPricingStrategiesLib”
...
The name of a Groovy Library which contains the custom strategies' generated code.
It doesn’t have to exist, it will be created during the first deployment.
...
customBlocksGroovyLibraryName
...
“StrategyDesignerCustomBlocks”
...
The name of a Groovy Library which contains definitions of custom blocks.
Learn how to define custom blocks in How to create custom blocks in Groovy.
...
excludedParameters
...
[]
...
A list of default PSP parameters you want to exclude. Specifying them will hide the blocks from the workspace. See How to exclude out-of-the-box PSP parameters for details how to do that.
...
additionalParameters
...
{}
...
A list of additional PSP parameters you want to see as blocks. Typically, you would need to specify any additional parameters you created in your customized PSP logic. See How to add additional PSP parameters for more details.
...
The Strategy Designer offers you to use some of the out-of-the-box parameters calculated by PSP as blocks in your strategies. But if they’re not configured properly in the PSP, they won’t work and will result in errors in the Strategy Designer. In such a case, it is better to hide them from the toolbox so the users don’t use them.
In case you don’t want to use them, you can specify them in the list of excluded parameters and the Strategy Designer will hide them from the toolbox. The following PSP parameters are supported:
PRODUCT_COST - comes from the standard Cost Lookup
BASE_PRICE - comes from the standard Actual Price Lookup
PLUS_FOR_PRODUCT_ABSOLUTE - comes from the Cost Plus Lookup
PLUS_FOR_PRODUCT_PERCENTAGE - comes from the Cost Plus Lookup
PRICE_INCREASE_ABSOLUTE - comes from the Price Increase Lookup
PRICE_INCREATE_PERCENTAGE - comes from the Price Increase Lookup
Here is an example of the configuration object that hides the last four parameters:
Code Block | ||
---|---|---|
| ||
"configuration": {
"excludedParameters": [
"PLUS_FOR_PRODUCT_ABSOLUTE",
"PLUS_FOR_PRODUCT_PERCENTAGE",
"PRICE_INCREASE_PERCENTAGE",
"PRICE_INCREASE_ABSOLUTE"
]
} |
You can also easily hide all PSP parameters like this:
Code Block | ||
---|---|---|
| ||
"configuration": {
"excludedParameters": "ALL"
} |
...
Status | ||||
---|---|---|---|---|
|
In case your custom price list logic uses some additional parameters (typically configured for Custom Engines), you can add them as blocks using the additionalParameters
option.
The additionalParameters
parameter is an object where each key is the PSP’s identifier of the parameter and the value is an object with a label
and a type
. The label
will become the text displayed on the corresponding block in the toolbox and the type
will become the return type of that block. Supported types are Number
, Boolean,
and Text
.
Say we have two additional parameters called ‘RRP’ which is a number, and ‘IS_OUT_OF_STOCK’ which is a boolean value (true or false). This is how you would make them available in the Strategy Designer’s toolbox:
Code Block |
---|
"configuration": {
"additionalParameters": {
"RRP": {
"label": "RRP",
"type": "Number"
},
"IS_OUT_OF_STOCK": {
"label": "Is out of stock?",
"type": "Boolean"
}
}
} |
Each key in the additionalParameters
object has to be unique. Make sure there are no syntax errors in the JSON object.
The parameters will be available in the toolbox under the Parameters category:
...
Status | ||||
---|---|---|---|---|
|
If the blocks provided by the Strategy Designer out-of-the-box are not enough, you can define your own using Groovy.
Create the Groovy Library
Follow these steps to create the library:
Create a Groovy Library and name it for example ‘StrategyDesignerCustomBlocks’ (remember this name for later)
In the library, create the first element and call it Meta. Set its Display Mode to Everywhere. More on the Meta element later.
Create other elements (at least one) which will contain the functions your custom blocks will call.
The Meta Element
The Meta element must return an array of objects, each object representing a block you want to create in the Strategy Designer.
Each block has a label and can contain parameters (block inputs where other blocks can be plugged in). The block will then call a specified custom Groovy function located in another element of this library, passing the values of the user-provided parameters to it.
The block object has the following structure:
...
Property
...
Type
...
Description
...
element
Status | ||||
---|---|---|---|---|
|
...
String
...
The element where the Groovy function which the block calls is located
...
function
Status | ||||
---|---|---|---|---|
|
...
String
...
The name of the function in the element specified by the element
property, which the block calls.
...
params
Status | ||||
---|---|---|---|---|
|
...
List
...
A list of parameter objects specifying the inputs of the block.
Each parameter object has the following properties:
name
- String - a unique name of the parametertype
- String - the type of the parameter, either number, string, or optiondefault
- default value supplied if the user doesn’t provide the input; its type must correspond with thetype
propertyoptions
- specified only if thetype
is option. It is either a list of values, or a map where the key is the option’s value and value is the option’s label.
...
label
Status | ||||
---|---|---|---|---|
|
...
String
...
The label rendered on the block. It can contain parameter placeholders like {1}
, {2}
, etc. If params
are specified, each parameter will be rendered at the position of the corresponding placeholder, so the first parameter will be rendered at the {1}
placeholder, the second at the {2}
placeholder, and so on.
If no placeholders are specified, the parameters will be all added at the end of the block.
...
color
Status | ||||
---|---|---|---|---|
|
...
Integer or String
...
The color of the block. It can be either an integer value (0 to 360) representing HSV hue value, or a #rrggbb String representing a web color.
If no color is specified, the block will have the default color of the Functions toolbox category.
...
tooltip
Status | ||||
---|---|---|---|---|
|
...
String
...
The tooltip of the block which is displayed when the user hover the pointer over the block. If empty, no tooltip will be displayed.
...
returns
Status | ||||
---|---|---|---|---|
|
...
String, either number or string
...
The return type of the block. It should correspond with the type of the return value from the function defined by the element
and function
parameters.
Examples of Custom Blocks
Arithmetic block
Let’s say we want to create an arithmetic block for calculating a percentage mark-up, that will look like this:
View file | ||
---|---|---|
|
Create the Meta element and return a list with a single block configuration object from it, like this:
Code Block language groovy return [ [ "element" : "Math", "function": "markupPct", "label" : "{1} x (1 + {2})", "params" : [ ["name": "base", "type": "number"], ["name": "markup", "type": "number", "default": 0] ], "returns" : "number" ] ]
Notice the label containing the placeholders that make the inputs render at the correct places.
Create a Math element and in it create a function called markupPct with two parameters, like this:
Code Block language groovy BigDecimal markupPct(BigDecimal base, BigDecimal markup) { if (base == null) { throw new Error("The base cannot be empty"); } if (markup == null) { return base; } return base * (1 + markup) }
You can the element and the function whatever you want as long as it is the same name as specified in the
element
andfunction
properties in the block configuration object.
Info |
---|
If you have multiple custom blocks, return all of them in the list returned by the Meta element. |
Tip |
---|
Pro tip: You can have as many or as few elements with your functions as you want. A good practice would be to group your functions in elements with a similar purpose, like Math, Text or Competition Data. |
Block with a drop-down
Let’s say we want to create a block that will retrieve an aggregation of prices of a selected competitor. The block should look like this:
...
Create the Meta element and return a list with a single block configuration object from it (or append the object to the existing list of objects), like this:
Code Block language groovy def competitorsIt = api.stream("PCOMP", "competitor", ["competitor"], true) def competitors = competitorsIt.collect { it.competitor } competitorsIt?.close(); def operatorOptions = [ "MAX" : "highest", "MIN" : "lowest", "AVG" : "average", "SUM" : "total", "FIRST": "oldest", "LAST" : "latest" ] return [ [ "element" : "Competition", "function": "competitorPrice", "status" : "active", "label" : "Get {1} price of competitor {2}", "params" : [ ["name": "operator", "type": "option", "options": operatorOptions], ["name": "competitor", "type": "option", "options": competitors] ] ] ]
Notice how we first retrieved the available options from the PCOMP table (line 1) and mapped it into an array of competitor names (line 2). We used this list of competitors in the
competitor
input parameter (line 22). Instead of a list, we could also feed it a map where the key is a competitor ID and the value is the competitor’s name, if necessary. We took this approach with theoperatorOptions
(lines 5 and 22).Create a Competition element and in it create a function called competitorPrice with two parameters, like this:
Code Block language groovy BigDecimal competitorPrice(String operator, String competitor = null) { def filters = [] if (!operator) { return null } if (competitor) { filters << Filter.equal("competitor", competitor) } def records = api.productCompetition(Filter.and(filters.toArray())) records.forEach { api.trace 'Record', it.infoDate + ' | ' + it.competitor, it.price } if (!records) { return null } switch (operator) { case "MAX": return records.max { it.price }?.price case "MIN": return records.min { it.price }?.price case "AVG": return records.sum { it.price } / records.size() case "SUM": return records.sum { it.price } case "FIRST": return records.sort { a, b -> a.infoDate <=> b.infoDate }.first()?.price case "LAST": return records.sort { a, b -> a.infoDate <=> b.infoDate }.last()?.price default: return null } }
Update the configuration
When your Groovy library is configured, you just need to tell the Strategy Designer that it should read it and create blocks from the definitions. You can do it by specifying the customBlocksGroovyLibraryName
option and setting it to your library’s name.
For example:
Code Block | ||
---|---|---|
| ||
"configuration": {
"customBlocksGroovyLibraryName": "StrategyDesignerCustomBlocks"
} |
When you reload the Strategy Designer, it will show all the defined blocks in the Functions category in the Strategies toolbox:
...
Limitations
The Strategy Designer is being actively developed. Here is a list of its known limitations:
English only - other languages are not supported at the moment, even if you switch to another language in the Unity settings
Pricing is supported only on the independent level, the same as the Live Preview. Dependent levels are not supported at the moment.
Limited multi-user access. Each user can have his own draft, but only one active deployed configuration can be stored. When deployed, you cannot go back at the moment.
Extended user permissions. Because the Strategy Designer needs to modify formulas and have access to master data and price lists & grids, it needs to be given certain permissions. The users will then gain access to certain Pricefx features, which they otherwise might not have access to.
Frequently Asked Questions
Q: I cannot see the Strategy Designer in the main menu. Why?
A: You probably don’t have the StrategyDesigner business role assigned. If you have, please check the configuration options, maybe there is another business role specified that you need to have.
Q.: Strategy Designer gives me a ‘Not authorized’ error when I try to open it. What can I do?
A: Please check if the StrategyDesigner business role has all the needed permissions. You can find them here.
Q: Can I use the Strategy Designer to modify other logics, such as Quotes or Rebates?
A: No, the Strategy Designer works only in tandem with the Price Setting Package accelerator. No other use cases are supported at the moment.
Q: I have changed a data lookup but the change is not reflected in my strategy. Is that a bug?
A: You probably forgot to save the data lookup. You need to save it even when you rename it. Otherwise, the new name won’t be reflected in your strategy.
Q: I have set up a range data lookup and want to change it. But the ‘Enable range lookup’ is disabled. Why?
A: If the lookup is already used in a strategy, you cannot change the range definition. You either need to delete the corresponding lookup block from your strategy, or create a new one by duplicating this one and saving it as a new data lookup.
...
Further reading:
Child pages (Children Display) |
---|