Recommended Logic Structure for Line Item Calculation Logics

Recommended Logic Structure for Line Item Calculation Logics

Based on experience, it turns out that there are different element types that follow a certain logical structure. This table shows how to organize these elements into corresponding blocks based on their logical order.

Element Block

Element Name

Sample Code

Display

Comment

Element Block

Element Name

Sample Code

Display

Comment

Gathering data needed for parameters gathering

SalesOrgs

if (!api.global.salesOrgs) {
api.global.salesOrgs = api.findLookupTableValues("SalesOrg")

.collect {
it.name
}
}
return api.global.salesOrgs

None

Only queries really needed for parameters gathering should be placed in this block.

Keeping each data query in a separate element avoids an element timeout.

Make sure the display is set to None, so this value does not get persisted.

Input parameters gathering elements

SalesOrg

api.inputBuilderFactory()
.createOptionEntry("SalesOrg")
.setOptions(out.SalesOrgs)
.getInput()



Keeping each user entry / input in a separate element is useful when testing the logic.

Currency

api.inputBuilderFactory()
.createOptionEntry("Currency")
.setOptions(out.SalesOrgs)
.getInput()



...

...



Stopping input generation execution element

AbortInputGeneration

if (api.isInputGenerationExecution()) {
api.abortCalculation()
}

None

Cancels the calculation run if running in the input generation mode (parameters gathering).

See also: Prevent api.isInputGenerationExecution Issues

 In release 10.0 Bees Knees, api.isInputGenerationExecution() replaces api.isSyntaxCheck(), which will however remain supported for backward compatibility.

Marked item dirty check element

ReferencePrice

...
if (needsSecondPass) {
api.markItemDirty()
// api.abortCalculation() - to be considered
// return - to be considered
}
...



It is good to check if the item needs a next pass at the very beginning of the logic if you plan to call api.abortCalculation.



Data gathering for logic calculation

CostRecord

def filters = [
Filter.equal("Cost"),
...
]

def pxCosts = api.find("PX", 0, 1, null, *filters)
return pxCosts ? pxCosts.getAt(0) : null

None

Returns the PX Cost records at one place and other elements can refer to it.

Make sure the display is set to None, so this value does not get persisted.

Keeping this query in a separate element is useful when testing the logic.

The data querying for big data should be done using api.getBatchInfo(). There is a sample code in BatchUtils in Shared library.

Margin

return api.vLookup("Margins", ...)



MinMargin





...

...



Calculation elements

CostPlus

if (out.Cost != null && out.Margin != null) {
return out.Cost * (1 + out.Margin)
}

return null



Calculates all the elements using the data queried in the previous block.

...

...



Result price element

ResultPrice

return out.CostPlus



Calculates the result price.

Auto-approve element

AutoApprove

def isAutoApproved = ...

return isAutoApproved ? 1 : 0



For LPG calculation the auto approval element can be placed here.

Found an issue in documentation? Write to us.