Skip to content
  • There are no suggestions because the search field is empty.

Advanced calculations

Raw data entry is only the start of your digital quality management. Based on this data, you want to make decisions and steer your operation. These decisions rely on predefined business rules and logic. Imagine how effective and powerful your quality system would be if it could apply these rules and logic automatically. Well, that is exactly what AlisQI is capable of with the expression engine.

The calculations that you can add to analysis sets are powered by our expression engine. This versatile engine enables you to implement rich logic in your analysis sets. Combined with the workflows, this enables you to create business logic within AlisQI.

This article presents an overview of how to create and use advanced expressions in AlisQI. Due to the vast possibilities, this guide is necessarily incomprehensive. Please refer to the resources on the bottom of this page for full documentation of the underlying syntax and available features.


Let's start with a short introduction video on the power of the AlisQI expression engine.


Syntax and features

The expression engine is based on Twig, an open-source templating engine.

The expression engine supports a rich syntax with many features, including functions, filters, tests, and operators.

Since the expressions run in a sandboxed environment there is no security risk. Users can never get to the core application code by means of the expressions engine.


All result values are available in the expression engine as variables. These variables are defined in braces, just like the field name in the example below:

During the evaluation of the expression, the variable contains the value of that particular field. Calculated values are available as well. This enables you to create complex, nested expressions.


Twig provides a variety of operators for math, logic, comparisons, and other means.

Here are two examples to show you a few possibilities of operators.

1. if the user is known, display the username, display 'unknown user' otherwise

'Hello, ' ~ ({user_} ? {user_} : 'unknown user')

2. if the remainder of a divded by b is non-zero, return b, else 1

{a_} // ({b_} != 0 ? {b_} : 1)


Variables can be modified by filters. Filters are separated from the variable by a pipe symbol (|). Multiple filters can be chained. The output of one filter is applied to the next.

The 'upper' filter would convert 'diana' into 'DIANA'


The 'capitalize' filter would convert 'diana' into 'Diana'


See Twig documentation on filters


Functions can be called to generate content. Functions are called by their name followed by parentheses () and may have arguments.
For instance, the date function can convert date(time)s. The following function call returns the current date minus 2 days:


See Twig documentation on functions


Tests can be used to test a variable against a common expression.

{numericfield_} is odd
'pass' in {status_}

See Twig documentation on tests

Greater than and less then operators

Values with a < or > sign are inaccurate by nature. Calculating these values can be risky, as the outcome can be inaccurate. AlisQI aims to keep the data accurate. This can lead to not performing a calculation that cannot be resolved to an accurate value.

Learn all about AlisQI's behavior with these operators here

Beyond result values

The expression engine offers more data than just the result values. You also have specifications, field visibility, attachments, and more available to use. All this to empower you to build rich business logic into your quality system.
The table below defines the entire context available in the expression engine.


The value for a particular field in your analysis set. Can be null.
For selection fields, this is the string value of the chosen option (e.g., "Pass").
For selection fields only
The option's static id, as integer numeric value. Use this to prevent changes to the option value (e.g., from "Pass" to "OK") from impacting the calculation.
For selection fields only
This syntax allows you to retrieve all field values from a selection list option. See example #7 below.
(Technically speaking, the .option is a hash of the selected option's values.)
For fields with a set relation only
This syntax allows you to retrieve all field values from a linked result. The field_ value in the linked result is used with this reference.
{field_}.spec The current specification values for this field.
For numeric fields (including calculations), this is a hash with keys min, innermin, goal, innermax, max. Access any boundary using {field_}.spec.min.
For selection fields, this is a list (array) of in-spec options (e.g., ['White', 'Transparent']).
{field_}.specLabel A pretty formatted representation of the specification. Numeric values are rounded to the right number of decimal positions.
For numeric fields with a lower and an upper limit it returns: [min value] - [max value].
For numeric fields with only a lower or only an upper limit it returns: "Min. [value]" or "Max. [value]".
For selection lists a comma separated list of in-spec options is returned, i.e. "White, Transparent" 
{field_}.offspec and
For selection and numeric fields only

Boolean value which indicates whether the

value is outside of (internal) specification.

{fieldname_}.label and
The field's label and unit (if any, can be null).
{fieldname_}.decimals and
For numeric fields (including calculations) only
The field's number of decimals and default (if any, can be null).
{fieldname_}.visibility The current field visibility state for this field.
For numeric fields (including calculations) only
The operator (< or >) set for this field (if any, can be null).


The list (array) of filenames, e.g., ['CoA.pdf', 'Delivery by pallet.jpeg'].

Reference other sets or lists

Analysis sets can link to other sets or selection lists. Data in these connected sets and lists can be accessed via the .option and .relation properties.

Selection list reference

{fieldname_}.option.field only applies to selection list form elements.
This can be read as: Follow the selected option in the selection list {fieldname_} and find the {field_} property for that particular option.

Set relation reference

{fieldname_}.relation.field only applies to field with a set relation.
This can be read as: Follow the set relation, and take the value of {field_} in the connected result.

If a set relation links to multiple results, the value of the most recent result is used.

User, Set and Result properties

The table below describes a collection of properties of the User, Set and Result that can be used in calculations.

Property Description
resultId Numeric value representing a dynamic generated id value for the result invovled. Ids are unique within the scope of an analysis set. Numeric value representing the logged in user's unique id.
user.fullname Text value representing the logged in user's given name, as managed via user management.
user.usergroup Text value representing the logged in user's usergroup, as managed via user management.
user.emailaddress Text value representing the logged in user's emailaddress, as managed via user management. Numeric value representing this set id. Example: 16 Text value representing the set name. Example: "Final product tests" Text value representing the set group name. Example: "Quality Control"
set.path Text value containing the set group and name joined by a slash. Example: "Quality Control / Final product tests"



To demonstrate the power of the expression engine, we now go through some real-life examples. These are just meant to inspire you. The possibilities are endless. Dive into the resources and go nuts!

Expiry date
Calculate the expiry date by adding 3 months to the production date

DATE_ADD_MONTH({productiondate_}, 3)
Alternatively, we could use the date filter to transform the production date string to a unix timestamp, add the necessary number of seconds, and convert back to a date string.
({productiondate_}|date('U') + 3 * 30 * 24 * 60 * 60)|date('Y-m-d')

Logical expressions

If (condition) then (A) else (B) 

Can be defined as: 

condition ? A : B

Read here about how to use logical operators in your expressions.

Use goal spec if no value was inputted
Use the inputted value, or fall back to the goal spec if no value was inputted. (Uses the ternary operator)

{ph_} ?: {ph_}.spec.goal

Test if an attachment was uploaded

attachments is empty 
? "No attachments"
: ("Number of attachments: " ~ attachments|length)

List all pdf attachments

attachments|filter(att => att ends with '.pdf')|join("\n")

Find the lower of two dates
Convert date1 and date2 to timestamps, determine the minimum value, are transformed back to yyyy-mm-dd.

MIN({date1_}|date('U'), {date2_}|date('U'))|date('Y-m-d')

Actually, thanks to the formatting of date strings (yyyy-mm-dd), we can compare the date strings directly.

MIN({date1_}, {date2_})

Convert a date's timezone

AlisQI stores it's date and time values in UTC timezone. For some applications you might want to convert this to another timezone. This can be done with the date filter:

{mydatefield}|date("Y-m-d H:i:s", "Asia/Tokyo")
This supports all timezones listed here.


User's name and email address
Suppose the field assignee_ is a selection field based on the user list. The following will evaluate the chosen user's address.


Test if a result has off-spec values
You might want to trigger or deviation process in case a result has an off-spec value. The following expression tells you whether the result has an off-spec value:

offspec|filter(s => s) is not empty 
? "Has off-spec values"
: "No off-spec values"

Errors and warnings

The enormous flexibility offered by the expression engine does come with a price. It's possible to create calculations that will run into problems.

AlisQI will try to validate the calculation by evaluating it using dummy values, but it cannot possibly catch all errors. Therefore, a list of errors and warnings is displayed while creating the calculation, as well as in the result entry screen. Use the preview in the analysis-set management to test the calculation with different input without needing to actually store results.


Consider the following example for a numeric calculation: {$batch_}, where Batch is a text field. The syntax of this calculation is fine, but whether a batch number can be interpreted as a number depends on its value. "1234AB" will be interpreted as the number 1234, but "AB1234" cannot be interpreted as a number. AlisQI cannot predict what values will be used, so it can only warn that using a text field in a numeric calculation can cause issues.

Here's a more devious example, using a numeric field a : 1 + ({a} ?: {}). As long as the value for a is truthy (not empty and not 0), this calculation will evaluate to 1 + a, which will always be a number. However, if the value for a is empty, the engine will try to add a number and a hash, which isn't defined and causes an error.

Caveats and technical details

If you read Twig's documentation, you may have noticed a couple of discrepancies with the syntax of calculations. To understand the differences, let's dive into how calculations are evaluated.

First of all, calculation is enclosed in output delimiters: . Therefore, you cannot use Twig tags.

Next, the field variables (e.g., {field_}) are actually invalid syntax. AlisQI transforms these to values['field_']. Likewise, {field_}.spec.min is transformed to spec['field_'].min, etc. The sandbox context actually contains (only) the following variables: attachments, values, id, operator, decimals, default, label, unit. You can use these if you wish.

Natural language interface

!Stay tuned for updates soon!

Useful resources

Here are some suggestions for more information on the technology behind our expression engine.