How to Add New Input-Based Formula Type with Calculation Method and Inputs
To add a new Input-Based Formula Type with a calculation method and inputs, follow these steps:
Step 1 – Define Input-Based Formula Type
Navigate to the AGR_InputBasedFormulaTypes Company Parameter and fill in the columns:
Formula Type Name – Provide a name of the Formula Type that will be displayed in the dropdown in Input Based Formula. It will also serve as an identifier for the Formula Type, therefore it must be unique.
Calculation Engine Path – Provide a path to a calculation method in the format
libs.<name of lib>.<name of element>.<name of method>
. Keep in mind that there is no parentheses at the end of the path.Engine Calculation Parameters - Provide any Calculation Parameters that you may need, which parameters are available and what they provide can be found here [link to Calculation Parameters] article
(Optional) Input Generation Table Name – If the Formula Type requires some user inputs to be generated by InputManager, provide a name of another Company Parameter table that will store their definitions. Usually it’s a good practice to name the InputGeneration table using the name of the formula type with “InputDefinitions” suffix for ease of identification. For example if Formula Type is named “AGR_MyFormulaType” then the InputGeneration table name would be “AGR_MyFormulaType_InputDefinitions”.
Step 2 – Define Inputs
Inputs are managed by the InputManager solution available in AGR_InputLib library and described in How to Modify, Add and Remove Inputs.
All inputs used by FormulaTypes must be defined as ”Configurator Entry” (if they are to be displayed in Formula Definition) or as Broadcast (if they are to be displayed in Agreement Line Item).
Keep in mind that the Input Name provided in the InputGeneration table can be used as a calculation parameter that is passed to the Calculation method defined in Step 3.
For example if the Input is named “header_myHeaderValue” it can be passed into Calculation Parameters SKU,FORMULA_INPUTS,header_myHeaderValue, which in Calculation method would look like:
Map calculate(String sku,
Map formulaInputs,
String header_myHeaderValue) {
<Calculation Body Here>
}
Step 3 – Define Calculation method
Calculations are handled by the EngineCalculator solution that is present in AGR_FormulaLib library.
The calculation method has to follow a certain signature. First the name of the method has to match the name (and place) that the Calculation Engine Path in AGR_InputBasedFormulaTypes Company Parameter points to. Second it has to have the Engine Calculation Parameters defined in the same order as in AGR_InputBasedFormulaTypes Company Parameter and of an appropriate type.
More on types and available Calculation Parameters can be found here [link to Calculation Parameters] article.
EngineCalculator requires a certain structure to be returned from your calculation method; the structure can be looked up in the createEngineResult
method in EngineCalculator and it is as follows:
[result : result,
message : message,
messageType : messageType,
additionalInfo : additionalInfo]
where:
result
key stores the result value (final price) of your Calculation Engine. This value is stored in Condition Records in the Engine Result column.message
key can store any message in String format that you wish to return from the engine, it can be a calculation status or something else. EngineCalculator automatically fills this field if it is not overridden.messageType
can store the type of the message provided in themessage
key. EngineCalculator automatically fills this field if it is not overridden. The available values are stored inlibs.AGR_FormulaLib.EngineCalculator.MESSAGE_TYPES
.additionalInfo
can store anything else that you wish to return from the calculation. Our CostPlus utilizes this to return a Map with information such as calculatedResult, formulaDetail, baseAdderType, baseAdderSource all of which are stored in their appropriate columns in Condition Records.
Keep in mind that you may need to adjust the Condition Records structure to match your calculation and its results.
Exemple configuration
AGR_InputBasedFormulaTypes
Formula Type Name - AGR_DemoFormula
Calculation Engine Path - libs.AGR_InputBasedFormulaEnginesLib.AGR_DemoFormula.calculate
Engine Calculation Parameters - FORMULA_INPUTS,SKU,header_myHeaderValue
Input Generation Table Name - AGR_DemoFormula_InputGeneration
AGR_DemoForecast_InputGeneration
Lookup Key - AGR_DemoFormula
Input Name - demo_AdderInput
Execution Path - libs.AGR_InputGeneratorLib.AGR_DemoFormula.getAdderInput
Order - 0
Input Type - Configurator Entry
Is Active - true
The calculation method in pseudo code could look something like this:
Map calculate(Map formulaInputs,
String sku,
BigDecimal header_myHeaderValue) {
BigDecimal adderValue = getAdderValue(forecastInputs)
BigDecimal productPrice = getProductPrice(sku)
return [result : productPrice + adderValue + header_myHeaderValue,
additionalInfo: [productPrice: productPrice,
adderValue : adderValue]]
}
The input generation method could look something like this:
The following example should generate a Formula that will take some Product Price and add some static Adder value to it as well as the value from Header.
Tips & Tricks
If you throw an exception in the Calculation Method it will be caught and displayed nicely in the Calculation Outputs Result Matrix.