跳到內容

Automations

本頁內容尚未翻譯。

An automation rule is a trigger and a list of steps. Something happens — a row appears, a clock ticks — and Adminium walks the steps: send an email, wait two days, check something, take one of two paths.

Open Automations in the sidebar. The left column lists your rules; the right one shows the flow of whichever is selected.

A rule has exactly one trigger, and there are two kinds.

A record is created / updated / deleted in a table. This is the common one. You can narrow it further:

  • Only when this column changes (updates only) — the rule fires when status changes, and stays quiet when somebody fixes a typo in the notes.
  • Only when — a condition on the row itself. A rule that only wants trial sign-ups says so here rather than filtering later.

Every 5 / 10 / 15 / 30 / 60 minutes, or daily / weekly / monthly at a time in a timezone you choose. A schedule can also scan a table: For each record of appointments where starts_at is within the next 2 hours starts one run per matching row.

Once per record is the setting that makes that safe. An appointment ninety minutes away matches four consecutive fifteen-minute ticks; with “once per record” on, the reminder goes exactly once. With it off, every tick is its own run — which is what a rule like “every hour, for each overdue invoice, post to Slack” actually wants.

This is the part worth reading twice.

A record trigger normally hears only the writes Adminium made — a row somebody created in the dashboard, or through the API. If your own application writes directly to the same database, Adminium never sees it.

So a rule can also watch the table: once a minute it looks for rows that appeared since it last checked. The trigger panel tells you exactly which world you are in:

Also watches for rows written outside Adminium · every minute · via created_at

or

Watching is off: this table has no created_at-shaped column or increasing key, so only writes made through Adminium trigger this rule

A table can be watched when it has a creation or update timestamp, or an increasing integer primary key — that column is how “since last time” is answered without scanning the whole table. Deleted rows cannot be watched at all: there is nothing left to find.

A row deleted outside Adminium, and its key given again. SQLite hands a deleted row’s key to the next row, and an import or a restore can write one by hand. A “record created” rule claims a row by its key and its created_at, so the next row with the same key, made later, runs the rule as the new row it is; a row that was only changed carries the same created_at, and never runs it twice. A table watched by an increasing key alone has no moment to tell the two apart: there only a delete made through Adminium lets the key go (Adminium 0.3.35).

Watching starts from now. Switching a rule on does not send a welcome email to every user who ever signed up.

A row Adminium wrote and the watcher then saw is one run, not two. Both sides compute the same identity for the same occurrence, and only the first one through creates the run. Each change Adminium writes is its own run all the same, also when several changes of one row carry the same updated_at (MySQL keeps it to the whole second): three stage moves within a second are three runs, each with the row as it was before its own move.

Wait / delay holds the run — minutes, hours or days, up to 30 days. The run is not sitting in memory: it is a scheduled job, so a restart costs it nothing, and Workflow logs shows it as Waiting · resumes in 4 hours.

Two things happen when a waiting run wakes up:

  • The record is read again. A run that waited two days acts on the row as it is now, not as it was. A row that has since been deleted ends the run Skipped, with the reason in the trace.
  • The rule is checked again. A rule switched off while a run of it was waiting does not resume; the run ends Cancelled.

A condition compares something to a value. There are two shapes.

This record — a column of the row the run is about, with is, is not, contains, is greater than, is less than, is empty, is not empty. On a date column you also get four relative operators: within the next, within the last, was more than … ago, is more than … from now.

Related records — a count of rows in another table:

Count of offer_claims where user_id is this record’s id — is greater than 0

That is how a rule asks “did they claim it?” or “has this patient missed an appointment before?”.

On a yes/no column only is and is not apply, and the value is yes or no; it compares the same on every database. A count of related records cannot be used in the conditions of For each record on a schedule: keep the count in a column of the row and compare that.

Two comparisons behave slightly differently depending on where they run. is matches without regard to letter case everywhere. is not compares exactly when it runs as part of a schedule scan (there is no case-insensitive “not equal” in the query language) and without regard to case when it runs against a record in memory. If case matters to you, put the comparison in a filter step rather than in a scan’s where.

Only continue if stops the run when its condition does not match — the run still ends successfully, because the rule did exactly what it was told, and the later steps show as skipped.

If / else branch takes one of two paths. A branch cannot contain another branch.

Step What it does
Send email Renders one of your email templates and sends it. The relay’s reply becomes the step’s log line.
Send notification An in-app notice to everyone with a role, or to chosen people. It respects each person’s notification preferences.
Create record Adds a row to a table.
Update field Writes back to the record the run is about.
Call webhook POST or PUT to a URL, with the default JSON payload or your own text.
Slack message The same thing, with a { text } body and a hooks.slack.com URL.

An add-on may give steps of its own. They are listed in Add a step under From add-ons, each with its add-on’s name (“Offers & gift cards: Issue a voucher”), and the step’s card carries that name where another says ACTION.

  • Its fields are the add-on’s. Each is filled from a column of the record (its own, or one a link leads to, such as the order’s customer’s email) or with what you type; some are a choice, some a row of the add-on’s own table.
  • It adds one row for the add-on. Nothing else of the add-on runs in your rule: the add-on’s own rules then do what they always do with such a row (make its code, send its email).
  • You need the right to add that row. A step your role may not use says so in its fields.
  • A personal value stays personal. A customer’s address or name may fill a field only when the add-on keeps that value personal too. The workflow log says such a field was filled in, and never shows it.
  • If the add-on is removed, the step stays with its settings and its card says “The add-on … is no longer installed.” The rule cannot be switched on until the add-on is back or the step is removed; a run meanwhile fails with that sentence.

Anywhere a step takes text — an address, a webhook body, a column value, a notification title — you can pull from the record:

{{record.email}} {{record.full_name}} {{now}} {{ruleName}} {{recordLabel}}

Email templates read the same names, so there is one grammar to learn. A token Adminium does not recognise is left exactly as you typed it, which is how you find a mistake.

A token may say what to write when its value is empty: {{record.first_name|there}} writes “there” for a record with no first name. In the email step, a template’s variable that carries its own backup is marked Has its own backup text and needs nothing from the rule.

For a date column you can also pick Now instead of typing a value; Adminium writes the timestamp your database expects. A rule an app ships may also fill a value from the app’s settings (From settings: …) or with a day so many days after a date of the record (28 days after signed_at): the step shows such a value as it is, and it is worked out when the step runs.

A column the product masks (an email address, a phone number) can be read by a rule and sent to, but never written by one.

A code staff never see (a column with rules.code.hiddenFromStaff, such as an online order’s own link) is no token of a rule: a rule’s text reaches whoever its author says. Saving a rule whose step names one — {{record.share_code}}, {{share_code}}, {{was.share_code}}, or a linked row’s {{order_id.share_code}} — is refused with the column named. The app’s own emails still carry it to the row’s holder.

A rule saves at any stage — a half-built flow is a normal thing to leave overnight. It only runs once every step is finished, and the toggle says so: Finish “Send welcome email” before switching this rule on.

Changes to a flow are saved when you press Save (or ⌘S). Leaving the page with unsaved changes asks first.

Test runs the rule against the newest row of its table and executes nothing. Emails are rendered but not sent, writes are prepared but not written, webhooks are guarded but not called — and the flow lights up along the path the rule would actually take, including which side of a branch it would choose.

A test stops at an email step whose template reads a variable that nothing fills and that has no backup, and names it: fill it in the step, or give it a backup in the template. A real run would still send the email with the variable as written.

Undo, loops and the things that could go wrong

Section titled “Undo, loops and the things that could go wrong”
  • Undo. A record you create in the dashboard can be undone for 60 seconds, so a rule triggered by one starts a minute late. If you undo inside that window, the run is dropped and Workflow logs shows it as Skipped.
  • Loops. A rule’s own writes are events too. A rule never re-enters itself, and a chain of rules writing into each other’s tables stops after three hops with a line in the audit log.
  • Imports do not fire record triggers. A watching rule sees the imported rows anyway, on its next tick.
  • Bulk edits do fire them, once per row.

An app or an add-on may bring rules with it. They are listed below your own, under From your add-ons and From your apps, each with the name of what brought it.

  • The switch is yours. A rule arrives on or off as its maker chose; after that your switch stands, through every update.
  • The rule is not. A shipped rule opens read-only and cannot be deleted. Edit a copy makes an ordinary rule of your own from it; switch the shipped one off if the copy replaces it.
  • An update replaces it. A newer version of the app or add-on rewrites its rules and removes the ones it no longer ships. Your copies are never touched.
  • It rests with its add-on. While the add-on is switched off the rule is skipped, and the workflow log says so.
  • A schedule runs on your clock. A shipped rule names no time zone: it takes the database’s, else the server’s, and the card says which.

Automations and Workflow logs are behind a single permission, Manage automations and their logs, seeded to Super Admin. A super admin can grant it to another role on the Roles page.

A rule runs as the system, so it is not limited by the table permissions of whoever wrote it — which is why the save is checked instead: you cannot save a rule that reads or writes a table you yourself cannot.

See also: Workflow logs.