🚀 Quick Start

This is not a reference guide. It is the shortest path to having something that actually runs within an hour. Once it runs, then it makes sense to read the rest of the documentation.

This article assumes TAS is installed and a valid licence is loaded. Since version 5.17 the system runs without a licence, but templates cannot be edited, so you would get stuck in step 1. If you do not have a licence yet, go back to Get Licence.

1. Four concepts that get you started

Concept

What it is

Template

The blueprint of a process. This is where you configure everything: steps, forms, rules, code.

Case

One run of a template. One specific request, invoice or contract.

Task

One step of a case. It has a solver and a form.

Variable

A field that stores a value. You define it on the template, its value lives in the case.

One sentence worth remembering: the template holds the rules, the case holds the data.

The technical name of a variable is sacred

Every variable has a label (what the user sees, in any language) and a technical name (what you use in code). In code you work exclusively with the technical name, and it is case-sensitive.

vars['amount']   // correct - technical name
vars['Amount '] // wrong - label or a typo, will not work

Write technical names in English, without diacritics, in camelCase. Keep a list of the variables for each template. In three months it will save you an hour.

2. Your first process in 10 minutes (without a single line of code)

Goal: a simple purchase request. Someone submits it, someone approves it.

Step 1 - Create a template. Templates > new template. Name: Purchase request.

Step 2 - Create three variables. As of version 5.19 you have two options and both lead to the same result:

  • Manually - variable by variable, full control over the type and the technical name.
  • AI builder mode - you describe what the process needs and the builder proposes and creates the variables for you.

For your first template, do it manually at least once. The AI builder is faster, but until you know what a variable type and a technical name look like, you cannot tell whether it gave you what you asked for. Once you do know, switch to the builder. It saves a lot of clicking.

No matter how you create them, check the technical names afterwards. Those are what you will use in code.

Label

Technical name

Type

Amount excl. VAT

amount

Number

Purchase reason

reason

Text

Approver note

approvalNote

Text

Step 3 - Draw the process graph. Two tasks and a link between them:

[ Submit request ] ------> [ Approval ]
  • Submit request - solver: the case owner
  • Approval - solver: a specific user or a role (for testing, use yourself)

Step 4 - Assign the variables to the tasks and set the permissions. This is the most common place where beginners get stuck: a variable will not appear on the form until you assign it to the task.

Task

amount

reason

approvalNote

Submit request

W + M

W + M

-

Approval

R

R

W

  • R (Read) - visible, not editable
  • W (Write) - editable
  • M (Mandatory) - the task cannot be completed without it

Step 5 - Start a case and click it through. Create a case, fill it in, complete the task, complete the second task.

Do not add calculations until the whole process runs manually from start to finish. Otherwise, when something breaks, you will not know whether the problem is in the graph, in the permissions or in the code.

3. What a calculation is and when it runs

A calculation is a piece of JavaScript stored in the template that TAS runs on its own at a moment you choose. It runs on the server, it has no UI and the user sees nothing of it.

When it runs

Trigger

When it fires

Typical use

Case start

when the case is created

pre-filling values, assigning a number from a sequence

Task start

right before the user receives the task

preparing and fetching data for the form

Task end

after the user clicks Complete

recalculations, status changes, calls to other systems

Scheduled task / cron

on a schedule

bulk operations, integrations, notifications

Roughly 80 % of your logic belongs to task end. When in doubt, put it there.

What a calculation can and cannot do

Can: read and write variables, read and populate dynamic tables, call external REST APIs, generate documents, write to the log.

Cannot: change the form at runtime, which means hiding fields, marking something as required or recalculating a value while the user types. That is what form validation and dynamic conditions are for, both running in the browser.

Where you write a calculation

A calculation is not a separate object. It lives inside the template, on the task and trigger you pick. The trigger is therefore not something you configure in the code, you choose it when you create the calculation.

TO BE ADDED: the calculation editor. This section should cover the path to the screen (Template > task > ...), choosing the trigger (case start / task start / task end), a screenshot of the task detail with the calculation editor open and the trigger selector visible (callouts: 1 trigger, 2 code field, 3 save), and how to tell that the calculation is saved and active.

4. Your first calculation (three lines)

Add a variable amountWithVat (Number) to the template and put this on task end of Submit request:

const amount = vars['amount'].getValue();

vars['amountWithVat'].setValue(amount * 1.21);

proc.warn('VAT recalculated', { caseId: lib.iprocId(), amount });

Line by line:

  1. vars['amount'].getValue() - read the value of a variable from the current case.
  2. vars['amountWithVat'].setValue(...) - write the result back into the case.
  3. proc.warn(...) - log what happened. Do this from day one, otherwise you will be guessing when something breaks. Why warn and not info is explained in Logging.

Start a new case, fill in the amount, complete the task. In the second task, or in the case detail, you will see amountWithVat filled in. That is it, you can write calculations.

5. Five patterns that cover 90 % of your start

5.1 Reading and writing a variable

const amount = vars['amount'].getValue();
vars['result'].setValue(amount * 2);

5.2 Input validation belongs on the form, not in a calculation

When a user is about to fill something in incorrectly, do not let them find out only after clicking Complete. Since version 5.17 validation is configured directly on the form in the builder, so the user sees the error immediately, next to the field it concerns.

TO BE ADDED: form validation via the builder. This section should cover where in the builder validation is configured, which validation types are available (mandatory, range, format, conditional validation based on another variable), a screenshot of the configuration, and an example such as "the approver note is mandatory when the amount is above CZK 50,000".

Only put in a calculation what cannot be checked on the form, typically a check against an external system or against data the user cannot see.

5.3 Logging, and why proc.warn is your friend

proc.warn('VAT recalculated', { caseId: lib.iprocId(), amount });
proc.warn('Supplier not found', { supplierId });
proc.error('External call failed', { err: err.message });

Three levels are available, but in practice you will mostly use one:

Level

When to use it

proc.warn

Things you care about. They stand out in the log immediately and do not get buried among other records. This is your default choice during development and debugging.

proc.error

Something actually went wrong: a call to an external system failed, mandatory data is missing.

proc.info

Detailed operational records. Easily lost in the volume of entries, so not much use for debugging.

In practice: when you want to see what a calculation is doing, write it to proc.warn. Write messages in English. The second parameter is an object with context, whatever helps you trace the specific case. console.log does not exist in the TAS backend, see Three rules you must not break.

5.4 Working with dates

const today = moment();
const due = moment(vars['dueDate'].getValue());
const daysLeft = due.diff(today, 'days');

vars['daysLeft'].setValue(daysLeft);
proc.warn('Days left calculated', { caseId: lib.iprocId(), daysLeft });

moment is available in the sandbox, no import is needed.

5.5 Looking up a row in a dynamic table

A dynamic table is a global lookup table at environment level: price lists, suppliers, mappings. Its columns are named COL_1, COL_2 and so on.

const row = dt
.from('PRICE_TABLE', ['COL_1', 'COL_2']) // always list the columns you need
.whereCol('COL_1', vars['contractType'].getValue())
.getFirst(); // returns object or null

if (!row) {
proc.warn('No matching row in PRICE_TABLE', { caseId: lib.iprocId() });
return;
}

vars['price'].setValue(row['COL_2']);
proc.warn('Price resolved', { price: row['COL_2'] });
Do not skip the second parameter of from(), the list of columns. Without it TAS logs a warning and pulls unnecessary data.

6. Three rules you must not break

These are not style preferences. Breaking them makes a calculation fail silently, with no error message, which is the worst kind of bug.

6.1 No async, await, Promise, .then(), .catch()

TAS transpiles your code itself and handles asynchronous calls for you. Everything in TAS calculations is written synchronously.

// FORBIDDEN
const data = await client.get('/orders/1');
dt.from('TBL').whereCol('COL_1', x).getFirst().then(row => { ... });

// CORRECT
const data = client.get('/orders/1');
const row = dt.from('TBL', ['COL_1']).whereCol('COL_1', x).getFirst();

Yes, HTTP calls are written synchronously too. No, you do not need await. If you find an example with await somewhere online, rewrite it.

6.2 No console.log

The backend only has TAS logging: proc.warn, proc.error, proc.info. See Logging.

console.log belongs to the frontend (dynamic conditions, Case Overview), where proc.* does not exist.

6.3 The case ID is always lib.iprocId()

const caseId = lib.iprocId();   // correct
// not proc.IPROC_ID, not proc.IPROC_INST_ID

7. Cheat sheet

Variables

I want to

Code

Read a value

vars['name'].getValue()

Write a value

vars['name'].setValue(value)

Get the text form (title for a DT or list variable)

vars['name'].getTitle()

Get a JSON variable as an object

vars['name'].getJSON()

Write a JSON variable

vars['name'].setValue(JSON.stringify(obj))

Access variables on a multi-instance task

snaps['name'].getValue()

For a dynamic table (DT) variable, getValue() returns the index (a number) and getTitle() returns the text. In calculations compare by index, it does not depend on translations.

Case and task

I want to

Code

Get the case ID

lib.iprocId()

Read or write the case status

proc.getCaseStatus() / proc.setCaseStatus('APPROVED')

Get the case owner's name

proc.getCaseOwnerName()

Get a link to the case

proc.getCaseLink()

Get the task solver's name

task.getOwnerUserName()

Get a link to the task

task.getTaskLink()

Get the next number from a sequence

lib.getSequenceNumber('sequenceName')

Read variables of another case

lib.getSharedVariables(iprocId)['name'].getValue()

Other

I want to

Code

Get a row from a dynamic table

dt.from('TBL', ['COL_1']).whereCol('COL_1', x).getFirst()

Get multiple rows

.get() instead of .getFirst()

Log something I want to see

proc.warn(msg, ctx)

Work with dates

moment(), moment(x).diff(y, 'days')

Make an HTTP call

axios.getAxios({ baseURL, timeout }).get('/path')

Get a secret or password (Vault, 5.17+)

vault.get('KEY_NAME')

Validate user input

Does not belong in a calculation. Use the builder, see Input validation.

8. Form validation, dynamic condition, calculation, script

Four different things. Mixing them up means solving a problem on the wrong layer.

Tool

Where it runs

What it is for

Where you configure it

Form validation

browser (frontend)

checking what the user is filling in

builder, on the variable or form (no code)

Dynamic condition

browser (frontend)

form behaviour at runtime: hiding fields, requiredness, reacting to other values

in the template, on the task

Calculation

server (backend)

business logic, data, integrations

in the template, on a specific task or trigger

Script

depends on type

reusable code shared across templates

Administration > Scripts

Quick test:

  • "The user must not enter a negative number." - form validation in the builder
  • "I want this field hidden when the user ticks X." - dynamic condition
  • "I want to calculate and store this when the task is completed." - calculation
  • "I will need this function in three other templates as well." - script
Rule of thumb: whatever can be solved in the builder should not be solved in code. You save yourself maintenance and the user gets feedback immediately instead of after submitting.
A script must be marked as active, otherwise its functions are not available. A function defined directly in the template overrides a function of the same name from the scripts.

9. How to debug when it does not work

  1. Log from the very beginning. Put proc.warn('Step 1 done', { amount }) at key points. Without logs you are guessing, and warn shows up in the log immediately.
  2. Check the three rules. Roughly half of all mysteriously broken calculations contain an await or a console.log. See Three rules you must not break.
  3. Check the technical name of the variable. A typo or one extra capital letter gives you undefined with no error.
  4. Verify that the variable is assigned to the task and has the right permissions. A missing field on the form is usually not a code problem.
  5. Use debug.dump() to write all variables to the log. Useful when you do not know what the calculation is actually working with.
  6. Simplify. Comment out half of the calculation and try again.

10. Most common beginner mistakes

Mistake

Symptom

Fix

await or .then() in a calculation

nothing happens, no error

rewrite synchronously

console.log in the backend

nothing in the log

use proc.warn

Logging into proc.info

the record gets lost among the rest

put what you want to see into proc.warn

Label instead of the technical name

undefined

check the variable name

Variable not assigned to the task

the field is not on the form

assign it and set permissions

Input validation handled in a calculation

the user learns about the error only after clicking Complete

configure validation on the form in the builder

Form logic in a calculation

the field hides only after the task is completed

use dynamic conditions

Hardcoded token or password in the code

security issue

use the Vault: vault.get('NAME')

An invented function name that sounds right

the function does not exist

check the documentation or ask

11. What next

Once your first process is done, take it in roughly this order:

  1. Form validation in the builder - the fastest way to raise data quality without a line of code
  2. Case statuses (proc.setCaseStatus) - so overviews show where each case stands
  3. Dynamic conditions - hiding fields and making them required based on other values
  4. Dynamic tables - lookup tables, price lists, mappings
  5. Dynamic Rows (DR) - a table of items the user adds rows to
  6. AI builder for a whole template - once you know what a good template looks like, let it prepare one for you
  7. Print templates and Case Overview - PDF outputs and the case detail page
  8. Integrations via axios and the Vault - calls to external systems
Build your first template on something small and boring: a holiday request, an office supplies order, anything with three steps. Learn the full cycle on that, and only then move on to a real client process.

Frantisek Brych Updated by Frantisek Brych

4. 🔑 Get a license

🧩 Example use cases

Contact

Team assistant (opens in a new tab)

Powered by HelpDocs (opens in a new tab)