Formula Designer (Agreements)
Formula designer is a tool that enables Visual Configuration of Formula Types. It is tightly connected to the Agreements Accelerator architecture and based on Google Blockly.
The primary goal is to create simple Formula Types without the need for Groovy code.
Feature | Configures the following part of Agreements |
---|---|
Assign Calculation Parameters as parts of Calculation | Calculation Method Calculation Parameters |
Define Calculation Formula using drag and drop feature | Calculation Method of a Formula Type |
Assign inputs to various parts of Calculation using the customizable Input Blocks | Input Manager Input Generation Tables |
Customizable Result Block | Custom Outputs to Condition Records (requires additional configuration at project start) |
What Formula Designer is not:
Replacement for complex Formula Types (those can be implemented using Input-Based Formulas)
Visual Configuration for anything else than Formula Types for Agreements, there is no support for Quotes or any other modules.
Before the First Formula
If one is unfamiliar with Blockly it would be wise to take a moment and read the basic documentation about the solution here: https://pricefx.atlassian.net/wiki/spaces/ACCDEV/pages/4625006712
Installation
Formula Designer is embedded into the core release and is available from version 13.0.
Advanced Configuration
The Accelerator comes with a predefined configuration for Formula Designer, but it can be modified if necessary after deployment from Platform Manager.
To tweak the Formula Designer configuration, navigate to the Advanced Property called formulaDesigner
under Administration → Configuration → Advanced Configuration Options. There is a JSON file with properties as follows:
groovyLibraryName
– name of the library that stores the Activated Formula Types Calculation Methods Groovy Code.customBlocksGroovyLibraryName
– name of the library that contains definitions of Custom Blocks (functions).customInputBlocksGroovyLibraryName
– name of the library that contains definitions of Input Blocks.deploymentLogicName
– name of the logic that runs after the Formula Type has been Activated, this logic creates all necessary Company Parameter tables and deploys the Calculation Methods.excludedParameters
– unsupportedadditionalInfoFields
– defines additional connectors to the result block. This allows introduction of new fields that can be returned from the calculation method, for example, to be saved on Condition Records.additionalParameters
– defines additional calculation parameters that can be passed to the calculation engines. Remember that the calculation parameters need to be assigned to the engine first (see How to Add New Calculation Parameters to Calculation Engines).
User Permissions
The Accelerator comes with predefined permissions that allow viewing and managing Formulas. Ensure that all users who will utilize this feature have the appropriate Business Roles assigned. For more details, refer to the Business Roles (Agreements) article.
Creating Formula Type and Formula
Step 1. Create Formula
To utilize the Formula Designer, you must first create a Formula:
Navigate to the Side Menu → Agreements & Promotions → Formula.
Click Create New Formula in the top right section and fill in the details.
This creates a new Formula Custom Form that represents the instance of a specific use of (yet to be created) Formula Type. The Custom Form configuration can be found in Administration > Custom Form Types, named AGR_Formula.
After creating a Formula, it can be opened. The screen looks like this:
Step 2. Create Formula Type
Click Add Type or Edit Types, where Formula Type can be created.
The main workspace will look like this:
The ribbons define different Block sets. Each set provides different functionality.
Parameters - these blocks allow the use of Calculation Parameters during the calculation.
Data Lookups - contains all of your configured Data Lookups.
Constants - contains the following constants.
Text block - allows entering any static text value.
Math - contains blocks for mathematical operations, all accepting numerical inputs.
Number block
Arithmetic block
Rounding block
(round = half-up, round up, round down)Constrain block – limits the first value by a minimum (low) and maximum (high), both optional.
No price block – use this block as the final price of the formula if you do not want it to return any value.
Logic - contains blocks related to logical operations.
If-Then-Else block – if the value in the If input is true, then return the value in the Then input, otherwise, return the value in the Else input.
Evaluate block (aka Switch-case block) – allows you to evaluate a value plugged into the first input and then specify multiple If conditions to match the value being evaluated. The return value of this block is the return value of the first matched If block.
Logical and/or block – used to group multiple conditions together.
Comparison block – used to compare two values.
Is (not) empty block – returns true if the given input is (not) empty (null or empty text).
Boolean block – returns either true or false.
Inputs - contains blocks that represent Inputs handled by Input Manager. These blocks will be displayed either on the Details tab or on the Agreement under the specified label only if they are set as broadcastable.
When the label is not defined in the formula for an input, default fallback terms such as "Text Input", "Integer Input", etc., are displayed instead. Default label values can be changed within the AGR_FormulaDesigner_CustomInputs logic (Administration > Logics > Calculation Logic > Groovy Library).
The list of available inputs:
Boolean
Customer
Customer Group
Date
Date Range
Date Time
Integer
Product
Product Group
Seller
Seller Group
Slider
String
Text
Decimal
Functions - contains miscellaneous function blocks that are configured manually in Groovy code.
Step 3. Create Data Lookup (optional)
Data lookups allow you to specify a data set that can be reused across your Formula Types in different ways.
Data lookup can be created by navigating to Data Lookups tab and clicking the Add button above the list of lookups.
There are two types of lookups:
Company Parameter
Advanced Data Lookup
Company Parameter Lookup
These two simple lookups can be compared to Excel’s VLOOKUP function, as they fetch a single row based on a key or a set of keys. They always require all key fields to be specified and produce just one value. They do not allow filtering, sorting, or aggregating data.
Advanced Data Lookup
The Advanced Data Lookup works differently compared to the Company Parameter lookup. It separates data fetching from aggregation.
The data fetching part is configured in the Data Lookups tab. An advanced data lookup does not produce a single value but always fetches a set of rows. You can filter and sort the result as needed.
The aggregation part happens in your Formula Type, where you specify how to transform the rows to produce a single value.
The flexibility comes with a cost – the advanced data lookup is generally slower.
Do not use the advanced data lookup if you can achieve the same result with the simple one. The advanced data lookup is generally slower than the simple one.
The advanced data lookup supports these data sources:
Company Parameters
Product Extensions
Product Master
Customer Extensions
Customer Master
Competition Data
Step 4. Use Formula Type in Formula
After Formula Type has been created and is valid (indicated by a green circle with the word “Valid” near the Formula Name) it can be renamed by clicking the “pencil” icon, providing a new name and activated by pressing the Activate button.
Once Active, the created Formula Type will show up in the drop-down (if it does not, refresh the page) and can be selected. Its Blockly representation will be displayed in the Preview section below.
Step 5. Fill in the Details Tab
On the Details tab, the user is presented with any Inputs that are part of the Formula Type. The inputs can be defined in logics described in the Logic Documentation (Agreements) | Formula Logics article. The values filled in here will be passed to the Calculation into appropriate places. If any Input has been marked as Broadcasted then it will appear on the Agreement instead (after the Formula has been approved).
Additionally in the Attributes section a Text Description of the Formula can be added to easily describe its purpose. This can be done within the logics described in the Logic Documentation (Agreements) | AGR_FormulaHeaderAttributesConfigurator section of the Logic Documentation article.
Step 6. Submit and Approve the Formula
Once everything is complete, the Formula CFO can be renamed and sent through the approval workflow (if defined - using Approval Workflow Package).
Once approved, the Formula will become available on the Agreement.
Creation of Custom Functions
Custom Functions are created in the same way as in the Strategy Designer: https://pricefx.atlassian.net/wiki/spaces/ACCDEV/pages/4631658696. Note that the Accelerator comes with a library designed to be used for Custom Functions called AGR_FormulaDesigner_CustomBlocks.
Creation of Custom Input Blocks
Create Groovy Library that will store the Custom Blocks. Accelerator comes with a library named AGR_FormulaDesigner_CustomInputs that contains some premade inputs.
For a new library, follow these steps:
Create a Groovy Library and name it (write down this name for later).
In the library, create the first element and name 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 inputs will call.
The Meta element must return an array of objects, each object representing a block you want to create in 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 | Required? | Description |
---|---|---|---|
| String | Required | Location of the Groovy function which the block calls. |
| String | Required | Name of the function in the element specified by the |
| List | Optional | List of parameter objects specifying the inputs of the block. Each parameter object has the following properties:
|
| String | Required | Label rendered on the block. It can contain parameter placeholders like If no placeholders are specified, the parameters will be all added at the end of the block. |
| Integer or String | Optional | 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. |
| String | Optional | Tooltip of the block which is displayed when the user hovers the pointer over the block. If empty, no tooltip will be displayed. |
| Map | Optional | Meta block contains any additional information that user may want to pass to the Deployment logic. Whole Meta element is passed and can be read in unchanged form. |
| boolean | Optional | Defines whether the label placeholders should be displayed inline with the label text or not. |
| String, either number or string | Required | Use “string”, not utilized for Input Blocks. |
Example
As an example let’s create a new BigDecimal input that will provide some Adder Value.
Step 1. Create new Meta entry
In the Meta element of AGR_FormulaDesigner_CustomBlocks, let’s append the existing list with a new entry:
[
"element" : "InputGenerationFunctions", <--- this defines the element where we'll put our function that will generate the input
"function" : "generateAdderValueInput", <--- this defines the name of the function that will generate the input
"label" : "Adder Input Is Broadcasted {1}", <--- this will be displayed on the Block in the Blockly workspace, the Broadcasted flag is necessary so we leave it there
"color" : "#287F62", <--- this can be set to anything valid
"inlineInputs": true, <--- short input so this looks better if set to true
"meta" : [ <--- here we'll pass some additional information to the deployment logic so InputManager will know how to handle our new Input
"name" : "adderInput", <--- name of the input, if name is not passed then the Deployment logic will use "id" which is much less readable when debugging the code
"element" : "InputGenerationFunctions", <--- we pass the same element as in the "element" tag
"function": "generateAdderValueInput", <--- we pass the same element as in the "function" tag
"order" : 0, <--- here we pass the order used by InputManager, if the project know that certain inputs should be displayed in certain order (always) then this can me modified here
"defaultLabel": "Adder Input" <--- if the label of the input is not passed then this will be used instead (that is our case, because label is not present, may require change in getInputLabel to notify the code that the label is missing by `return meta.params?.label ?: meta.defaultLabel` )
],
"params" : [
["name": "isBroadcast", "type": "option", "options": ["Yes", "No"]] <--- allows setting the custom input as broadcastable
],
"returns" : "string"
],
Step 2. Create Generation Function
Navigate to the Element pointed by the Meta and create a function with the same name as the function property in Meta. In our case this will be something like this:
ConfiguratorEntry generateAdderValueInput(Map inputs, Map meta) {
String inputLabel = getInputLabel(meta)
ContextParameter inputContextParameter = api.inputBuilderFactory().createUserEntry(meta.inputId)
.setLabel(inputLabel)
.buildContextParameter()
return libs.AGR_InputLib.CommonInputGenerationUtils.buildConfiguratorEntry(inputContextParameter)
}
This function will generate a new “Adder Value” input block that will be possible for selection under Inputs tab. Meta map is crucial here, because it contains all meta from the previous step but also all parameters (with user filled values) and inputId, in case name is not provided. If everything is filled correctly then Deployment logic will handle the rest of the process. Notice that the function returns ConfiguratorEntry, this has to be the case for all input blocks.
Formula Activation logic
Activation or Deployment – these two terms can be used interchangeably when talking about what happens after Activate is clicked on the Formula Type Draft.
The deployment logic is defined under deploymentLogicName (Administration > Configuration > Advanced Configuration Options > formulaDesigner) and set to AGR_FormulaDesinger_Deployment by default (located in Administration > Logics > Calculation Logic > Generic Logic). This logic is executed after Activate is clicked. In the case of Accelerators, it does a number of things.
Populate Inputs
If there are any inputs used by the Formula Type, then their respective Input Generation tables need to be created. This process follows the same principle as for regular inputs.
First the Input Generation table is created by following the pattern defined by: libs.AGR_ProcessingLib.ConstConfig.FORMULA_DESIGNER_CONFIG.INPUT_GENERATION.PRICE_PARAMETER.NAME_PATTERN, which by default is AGR_YourFormulaName_InputDefinitions.
The Input Generation table is filled based on the meta of the Input block.
An important step is that the meta block is saved as one of the attributes of the table. This allows meta to be accessed by the generation function of the input, which can be handy.
Meta is also extended by two additional entries:
inputId
andparams
(which are user-filled values).
Populate Formula Types
After inputs have been generated, the last step is to create the entry in the FormulaTypes table pointed by libs.AGR_FormulaLib.ConstConfig.FORMULA_TYPES_PARAMETER_CONFIG. This step fills in data such as the formula name, calculation method path, or parameters (taken from the used blocks).