...
Configurator Logic
The logic is executed after clicking the Open button of Configurator.
After clicking the Save button of a popup Configurator, a new configurator value is saved to the Quote object. (Quote object is what you get by calling
quoteProcessor.getQuoteView()
.) But you cannot work with the values until the quote is recalculated. Why? All the logic knows is the old quote object since all other calculation logics finished before the configurator logic was executed. You must click the Recalculate button or set automatic recalculation; to learn more see how to recalculate a quote automatically.
Template Logic
The logic is executed after clicking the download PDF button.
From the template logic the whole quote object is accessible through
api.getCurrentItem()
.
...
Step 1: Create the Configurator button in the header logic.
Code Block | ||
---|---|---|
| ||
if (quoteProcessor.isPrePhase()) { quoteProcessor.addOrUpdateInput( "ROOT", [ "name" : "Configurator", "label": "Configurator", "url" : "ConfiguratorLogic", "type" : "CONFIGURATOR" ] ) } |
Step 2: Define a generic logic (name it e.g. “ConfiguratorLogic”). It contains input matrix in this example.
Code Block | ||
---|---|---|
| ||
def ce = api.createConfiguratorEntry() def p = ce.createParameter(InputType.INPUTMATRIX, "QuoteFeatures") def cols = ["Name", "Description"] def types = ["Text", "Text"] p.addParameterConfigEntry("columns", cols) p.addParameterConfigEntry("columnType", types) return ce |
Step 3: In the header logic, access all the values from the configurator using the following code snippet:
Code Block | ||
---|---|---|
| ||
if(quoteProcessor.isPrePhase()) { def quote = quoteProcessor.getQuoteView() def quoteFeatures = quote?.inputs?.find { it.name == "Configurator" }?.value } |
...
Let’s suppose you have the following header logic stringUserEntry field which you want to pass to the configurator:
Code Block | ||
---|---|---|
| ||
if (quoteProcessor.isPrePhase()) { quoteProcessor.addOrUpdateInput("ROOT", [ "name" : "ValueToBePassed", "label" : "ValueToBePassed", "type" : "STRINGUSERENTRY", "required": false ] ) } |
...
The issue here is that the configurator and header logic do not share a global space. So you cannot simply use api.global
. Instead, you need to pass this value to the configurator value
property.
Code Block | ||
---|---|---|
| ||
if (quoteProcessor.isPrePhase()) { def passedValue = quoteProcessor.getQuoteView().inputs?.find { it.name == "ValueToBePassed" }?.value quoteProcessor.addOrUpdateInput( "ROOT", [ "name" : "Configurator", "label": "Configurator", "url" : "ConfiguratorLogic", "type" : "CONFIGURATOR", "value": passedValue ] ) } |
...
{QuoteFeatures=[{Name=firstLineName, firstLineDescr, selected=false}], PassedValue=asdfasfd}
Code snippet:
Code Block | ||
---|---|---|
| ||
if (quoteProcessor.isPrePhase()) { def quote = quoteProcessor.getQuoteView() def passedValue = quote.inputs?.find { it.name == "ValueToBePassed" }?.value def configuratorValueBackup = quote.inputs?.find { it.name == "Configurator" }?.value ?: [:] configuratorValueBackup.put("PassedValue", passedValue) quoteProcessor.addOrUpdateInput( "ROOT", [ "name" : "Configurator", "label": "Configurator", "url" : "ConfiguratorLogic", "type" : "CONFIGURATOR", "value": configuratorValueBackup ] ) } |
...
To be able to read a value inside the configuration logic which was passed from the header logic, you need to use a HIDDEN input. The code illustrates this better:
Code Block | ||
---|---|---|
| ||
def confEntryPassedValue = api.createConfiguratorEntry(InputType.HIDDEN, "PassedValue") def passedValue = confEntryPassedValue.getFirstInput()?.getValue() |
...
Quote line logic:
Code Block | ||
---|---|---|
| ||
def value = api.global.variableTest api.logInfo("LineItemLogic value:" + value); |
...
If you use publishing templates for quotes, you have to pass data to the preprocessing (publishing) logic. To do that, simply call api.currentItem
from the preprocessing logic to get a full quote view.
Code Block | ||
---|---|---|
| ||
def quote = api.currentItem(). |
...
Thanks to the post-phase you can pass these values within one recalculation transaction.
Final code:
Code Block | ||
---|---|---|
| ||
if (quoteProcessor.isPostPhase()) { def quote = quoteProcessor.getQuoteView() def lineItems = quote?.lineItems def sum = 0 lineItems.each { lineItem -> def outputItems = lineItem.outputs def value = outputItems.find { it.resultName == "LineItemValue" }?.result sum = sum + value } def passedSumValue = sum def mergedValue = quote.inputs?.find { it.name == "Configurator" }?.value ?: [:] mergedValue.put("PassedValue", passedSumValue) quoteProcessor.addOrUpdateInput( "ROOT", [ "name" : "Configurator", "label": "Configurator", "url" : "ConfiguratorLogic", "type" : "CONFIGURATOR", "value": mergedValue ] ) } |
...
Why? Let’s see the example of passing values from a line item logic to a line item configurator.
Code Block | ||
---|---|---|
| ||
api.configurator("Configurator A","ConfiguratorFormula") def confA = api.getParameter("Configurator A") if(confA != null && confA.getValue() == null) { confA.setValue(["ConfiguratorType":"A"]) } |
...
Configurator at the header level, defined in the header logic. From this configurator, you load data to the line item configurator.
Code Block | ||
---|---|---|
| ||
if (quoteProcessor.isPrePhase()) { quoteProcessor.addOrUpdateInput( "ROOT", [ "name" : "Configurator", "label": "Configurator", "url" : "ConfiguratorLogic", "type" : "CONFIGURATOR" ] ) } |
...
This needs to be done in the quote header logic.
Code Block | ||
---|---|---|
| ||
def quote = quoteProcessor.getQuoteView() def lineItems = quote?.lineItems lineItems.each { lineItem -> def inputItems = lineItem.inputs def value = inputItems.find { it.name == "ConfiguratorName" }?.value sum = sum + value?.configuratorFieldValue? : 0 } |
...
It is possible to add default values to the line item configurator from the line item logic using the following code:
Code Block | ||
---|---|---|
| ||
api.configurator("Configurator A","ConfiguratorFormula") def confA = api.getParameter("Configurator A") if(confA != null && confA.getValue() == null) { confA.setValue(["ConfiguratorType":"A"]) } |
...