# Running, scheduling and accessing results

Reports belong to your account. You edit a draft; publishing creates a version
that never changes, with the report's XML and scripts stored inside it. Runs
and schedules use a published version, so editing the next draft cannot change a
result that is already scheduled.

## Previewing and running

**Preview** runs your draft against real data, with your own data permissions.
Preview files are kept in the database and marked as previews; check them before
publishing.

Running a published version starts a run and returns straight away; the report is
produced in the background. Supply the report's parameters and a request key: if
the same request is sent again with the same key, you get the same run rather than
a second one. Use a new key when you want fresh data.

When the run finishes, its files are listed with a download link. A download
always returns the saved file; it never produces the document again.

- **Retry** a failed run with the data captured when it first ran, as long as that
  data is still kept (see Storage and retention below).
- **Cancel** stops a run as soon as it safely can.
- **Archive** a report to stop new runs and schedules. Results that already exist
  stay available.
- A report definition can also be run once without adding it to your report list.

## Running one report for many parameter sets

A batch runs one published version with between 1 and 100 sets of parameters, under
one request key. The whole batch is accepted or none of it is, and repeating the
request with the same key returns the same runs. The CoCoCo app shows a batch
summary linking each result.

## Scheduling

A schedule runs a published version automatically: on a recurring timetable written
as a cron expression, or once at a set date and time. Times are in the time zone you
choose, by its IANA name such as `Europe/London`.

- **Who it runs as.** A schedule runs as a bot user. To create one you need
  permission to schedule reports (`report:schedule`) and to run reports as that bot
  (`report:useExecutionIdentity`). Each time it runs, the bot's current permissions
  for reports, data and files are checked again. No sign-in token is stored.
- **Pausing** a schedule stops its future runs.
- **Overlap.** If the previous run is still going, the next one is skipped and the
  skip is recorded. Allow overlap on the schedule to run them side by side instead.
- **Missed runs.** After an outage, missed runs are combined into one run for the
  latest time that was due, rather than catching up one by one.
- **Daylight saving.** A local time that does not exist on a given day is skipped;
  a local time that happens twice runs twice.
- **Relative periods.** A schedule can fill the report's `from` and `until` DATE or
  DATETIME parameters with the previous day, week or month, worked out in the
  schedule's time zone for the time the run was due. Weeks start on Monday. Without
  a period, parameters stay as set. To produce past periods, run a batch with
  explicit dates.

## Delivering results

A schedule can notify a recipient when its results are ready. The message contains
a link to the run, never the file or its data: the recipient signs in and needs
access to the report and its data, so this is not a way to share with people
outside your account.

Delivery needs your installation's public web address and notifications to be set
up. The person creating the schedule and its bot need permission to deliver reports
(`report:deliver`) and to read the recipient (`notificationRecipient:read`). Each
delivery attempt is recorded; *accepted* means the notification service took the
message, not that it was read. Delivery is retried up to five times, so in rare
cases a notification can arrive twice.

## Storage and retention

Each output is stored in one of two ways:

| Storage | Limit per output | Notes |
|---|---|---|
| `DATABASE` | 8 MiB | Kept with the run. |
| `FILE` | 32 MiB | Kept in your installation's managed file storage, optionally in a chosen folder. Needs file storage to be set up, plus permission to write files (`file:write`) and read the folder (`folder:read`). |

If the chosen storage is not available, the run fails; it never saves the file
somewhere else. A report can use both kinds for different outputs.

The data captured for a run is kept for the report's `snapshotRetentionDays`
(30 days by default, 1 to 3650), counted from when the run was queued, and only
removed once the run has finished. A run can be retried only while its data is kept.

Output files do not expire automatically, whether stored in the database or as
files. They remain available to people who have the original data permissions, and
archiving a report does not delete them. Set your own retention policy before
storing regulated documents.

## How the formats behave

- **CSV** files are UTF-8, comma-separated, with Windows (CRLF) line endings and
  quotes where needed. Empty values stay empty, and text a spreadsheet could treat
  as a formula is prefixed with an apostrophe. Spreadsheet programs may still drop
  leading zeros when they open a CSV file; use XLSX when that matters.
- **XLSX** workbooks store numbers and true/false values as typed cells and
  everything else as text, so leading zeros and formula-like text are kept. Whole
  numbers too large for Excel's precision are written as text. Formulas and macros
  are not supported. A workbook can have up to 16 sheets.
- **PDF** runs can produce up to 100 pages. Images must be embedded PNG or JPEG
  `data:` URIs of at most 1 MiB each and 16 million pixels in total; files on the
  server and web addresses cannot be used. Content that does not fit fails with an
  error instead of being cut off. The Designing report PDFs chapter covers
  layout; check the result with your production fonts and paper.

## Data, scripts and exact values

Queries run with the data permissions of whoever runs the report, or of the
schedule's bot. Look up the real table and field names before writing a query, for
example `erp_customers`. In MicroSQL, `ORDER BY` needs `ASC` or `DESC`; declare an
ordering so results come back in a stable order. Pass values as parameters; never
build them into the query text.

DATE parameters use `yyyy-MM-dd`; DATETIME parameters use ISO 8601 with a time-zone
offset.

The preparation script receives the report's data as `input` (its parameters,
context and datasets) and returns it. It is standard Lua with all of the language's
libraries, including decimal arithmetic: it cannot query data, call the platform or
load other scripts, so fetch everything it needs with `<source>` queries and use
preparation only to reshape the results. Transforms work the same way, one row at a
time: each receives a row as `input` and returns the row to keep, or nothing to drop
it.

For money and other exact decimals, keep values as strings or as whole minor units
such as cents, or use decimal arithmetic deliberately. Floating-point numbers lose
precision.

## Moving reports between accounts

The report editor can export a report as a package file and import one. A package
contains the report's source only: no runs, credentials or permissions. Before
publishing an imported report, check its data and folder settings for the new
account and preview it.

Starter reports are available as ready-made starting points, each with a note of
its limitations.

## Using reports in workflows

A workflow's `run-report` step starts a published report version with the
parameters you give it, and an optional occurrence key when it runs inside a loop.
It runs as the workflow's bot and returns the run's ID and status; the report is
produced separately.