Skip to Content
Products

Bundle steps

All fields of a product step and info step, and the formula with which a step determines its own invoice lines.

Last updated on

This page describes the fields in the Extra invoice lines card on the product page. How to build a bundle is described in Setting up extra invoice lines.

Product step

Tillor turns a product step into zero, one or more invoice lines with that product. Without a formula that is one line with the quantity you set; with a formula you decide yourself whether lines appear, how many and which.

FieldWhat it does
ProductThe product that goes on the child line, for example an NFC surcharge or meter rental. Required
QuantityThe quantity of the line if the step has no formula, or if the formula returns true. Greater than 0
Multiply by anchor line quantityMultiplies every calculated quantity by the quantity of the anchor line, for example 0.5 for half a year of Staangeld. The result is rounded to two decimals. Tillor leaves out lines that end up at 0 because of this; a line that the formula itself returns with quantity 0 stays
Description (optional)Replaces the product name on the invoice line. A formula that returns lines can give each line its own description
Line styleDefault (product), DEFAULT or INFO. With INFO the child line becomes a grey explanatory note on the PDF and in the editor
Once per invoiceOnly relevant if two or more anchor lines with a bundle are on the same invoice. The step then belongs only to the first anchor line in invoice order
Extra days after anchor end (access methods)Only useful if the main product has Extend Occupation Period as an action. When a line from this step is paid, Tillor extends the customer's access methods to the end date of the anchor line plus this number of days; types and statuses come from Extend access method on the main product, see Extending NFC via the bundle
FormulaOptional. TypeScript that decides whether the step appears on the invoice, with which quantity, or which lines exactly, see Formula per step

Info step

An info step is text only, without a product or amount. Tillor shows it as an explanatory line.

FieldWhat it does
Info line textThe visible text, for example "Inclusief toeristen-, gemeente- en provincietaksen". Required
Line styleINFO by default. You can choose DEFAULT if you want to show the line as a normal line
FormulaOptional. If the formula returns false, the info line is left out

If an info step is placed under an anchor line, the PDF automatically puts ↳ in front of the text.

Formula per step

Every step can have a Formula: TypeScript, just like the rate formula, which Tillor runs when an invoice with this bundle is saved. That way a step can depend on the customer, the occupation, the terrain, the meters or the access methods, for example via a custom field in which you record an exception.

What the formula returns

Returned valueEffect
trueOne line with the set Quantity
false or nullNo line
A number greater than 0One line with that number as quantity
A list of linesExactly those lines, in that order. An empty list means no line

A line in such a list is an object with these fields:

FieldMeaning
quantityRequired. The quantity, 0 or more. A line with 0 stays, even with Multiply by anchor line quantity
descriptionOptional. The description of this line; otherwise the step's Description, otherwise the product name
unitPriceOptional. Unit price including VAT, like the product rate; otherwise the product rate. 0 makes a free line
accessMethodValueOptional. The value of the access method this line is about (the UID of the NFC tag), for the extension on payment

What the formula can read

You read fields with curly braces, as in automations. The Variable menu next to the field shows everything that is available, including your own fields.

VariableWhat it is
{customer.…}The customer on the invoice, for example {customer.createdAt} or {customer.customFields.meterhuurVrijgesteld}
{occupation.…}The occupation of the anchor line. If the main product is not on Extend Occupation Period, it is the customer's only occupation; empty (null) if the customer occupies several terrains
{terrain.…}The terrain of that occupation
{anchor.…}The anchor line: {anchor.quantity} (for example 0.5 for half a year), {anchor.terrainId}, {anchor.occupationId} and {anchor.endDate}
{meters}The list of meters in scope: on the terrain of the anchor line with Extend Occupation Period, otherwise on all terrains the customer occupies. Each meter has name, provider (for example ICY), type (for example ELECTRICITY, GAS), the metadata of its provider (for example icyMetadata.switchState for supply on), its terrain and customFields
{accessMethods}The list of the customer's access methods, oldest first, of every type and status. Each method has type (for example NFC), status (for example ACTIVE), value, a readable label (the known name of the NFC tag, otherwise the value) and customFields

Tillor only loads the lists {meters} and {accessMethods} if the formula uses them.

Examples

Skipping a step for exempt customers:

if ({customer.customFields.exemptFromSurcharges} === true) return false;
return true;

One line per ICY electricity meter with supply on, and for customers since 2026 also with supply off:

const newCustomer = new Date({customer.createdAt} ?? 0) >= new Date("2026-01-01T00:00:00+01:00");
return {meters}
  .filter((m) => m.provider === "ICY" && m.type === "ELECTRICITY")
  .filter((m) => m.icyMetadata?.switchState === true || newCustomer)
  .map((m) => ({ quantity: 1, description: `Huur digitale elektriciteitsmeter ${m.name}` }));

The first NFC tag free as an explanation, every following one at the product rate (two steps with the same product, or one step that returns both kinds of lines):

const nfc = {accessMethods}.filter((a) => a.type === "NFC" && a.status === "ACTIVE");
return nfc.map((a, i) => ({
  quantity: i === 0 ? 0 : 1,
  unitPrice: i === 0 ? 0 : undefined,
  accessMethodValue: a.value,
  description: i === 0 ? `Toegangsmethode inclusief: ${a.label}` : `Toeslag extra toegangsmethode: ${a.label}`,
}));

One line with the number of dogs from a custom field of the customer, no line when there are no dogs:

const dogs = Math.max(0, Math.floor(Number({customer.customFields.animals.dogs}) || 0));
return dogs === 0 ? false : [{ quantity: dogs, description: `Honden (${dogs})` }];

With Insert example below the field you get a starting point with these forms in comments.

Errors

You cannot save a formula that does not compile; the message below the field says what is wrong. If a formula gets stuck when an invoice is saved, or returns anything other than true, false, a number or valid lines, saving fails with the name of the step in the error message, so that a broken formula never silently adds or leaves out a line.

See also

Was this page helpful?

On this page