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 the message key. EngineCalculator automatically fills this field if it is not overridden. The available values are stored in libs.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.