Reports
Reports generate a document (HTML or PDF) for a specific object using a Handlebars template. They are defined on a class alongside an optional context that brings in related objects, and triggered from a layout via an ACTION button.
Definition
{
"reports": [
{
"name": "invoicePDF",
"scope": "OBJECT",
"templateFile": "templates/invoicePDF",
"context": [
{ "relation": "invoiceLines", "sort": "lineNumber" }
]
}
]
}
| Property | Type | Description |
|---|---|---|
name | string | Unique name for this report within the class. |
scope | OBJECT | Only OBJECT is currently supported. |
templateFile | string | Path to a Handlebars template file in the repository, without the .hbs extension. |
context | ReportContext[] | Multiple-valued relations to include in the template context. |
What is automatically available
Single-valued relations (multiple: false) are always included in the template context one level deep — no declaration needed. If an invoice has a client relation, {{client.name}} works without adding anything to context.
context is needed in two cases:
- Multiple-valued relations (one-to-many or many-to-many) — these become arrays in the template:
{{#each invoiceLines}}. - Deeper nesting on a single-valued relation — if you need a multiple-valued relation on a related object (e.g.
client.addresses), declare the single-valued relation incontextwith a nestedcontextentry.
ReportContext
| Property | Type | Description |
|---|---|---|
relation | string | The relation name to include. Use the plural name for multiple-valued relations, the singular name for single-valued relations. |
sort | string | Optional sort order: "fieldName" for ascending, "fieldName,desc" for descending. Only applies to multiple-valued relations. |
context | ReportContext[] | Nested context, resolved relative to each matched relation object. |
Multiple-valued relation with nested context
A report on a project that includes each task's comments:
{
"context": [
{
"relation": "tasks",
"sort": "dueDate",
"context": [
{ "relation": "comments", "sort": "createdAt,desc" }
]
}
]
}
In the template, tasks is a list and each task has a comments list.
Single-valued relation with nested multiple-valued data
If client is a single-valued relation on the invoice, {{client.name}} is available automatically. To also access client.addresses (a multiple-valued relation on client), declare client in context with a nested entry:
{
"context": [
{
"relation": "client",
"context": [
{ "relation": "addresses" }
]
},
{ "relation": "invoiceLines", "sort": "lineNumber" }
]
}
In the template:
Template
The template receives the main object's fields as top-level variables. Single-valued relations are available as nested objects; multiple-valued relations declared in context are available as arrays.
Template files use the .hbs extension and are stored in the repository alongside the class files. Reference them without the extension in templateFile.
Triggering from a layout
Add an ACTION item with actionType: "REPORT" to open the report in a new browser tab:
{
"type": "ACTION",
"name": "invoicePDF",
"label": "Print invoice",
"actionType": "REPORT"
}
The name must match a report defined on the same class. See Layouts — ACTION for the full ACTION item reference.
Complete example
An invoice class with a PDF report that includes its lines, sorted by line number:
{
"class": "my-project.invoice",
"type": "BASIC",
"inherits": "commons.item",
"valueTypes": [
{ "name": "invoiceDate", "dataType": "DATE" },
{ "name": "total", "dataType": "CURRENCY" }
],
"reports": [
{
"name": "invoicePDF",
"scope": "OBJECT",
"templateFile": "templates/invoicePDF",
"context": [
{ "relation": "invoiceLines", "sort": "lineNumber" }
]
}
],
"layouts": [
{
"type": "OBJECT_DASHBOARD",
"items": [
{ "name": "name", "header": true },
{ "name": "invoiceDate" },
{ "name": "total" },
{
"type": "ACTION",
"name": "invoicePDF",
"label": "Print invoice",
"actionType": "REPORT"
}
]
}
]
}