Invoicing rules
Flow drafts the invoice of each billable job that is ready to invoice, by
rules, and sends checked invoices to the accounting system (Xero) in one of
two ways. Invoicing is part of Flow and needs no integration. With no
accounting system connected, Flow's own records are the only check: each job
gets at most one invoice. The send mode is on the Xero integration page. This page
describes the rules and the send modes. The code is in
server/core/invoicing-rules.js. The settings are in Flow under Settings,
Rules, and at /api/invoicing/settings.
From job to customer
flowchart LR
work[Job in work] -- a person, or the work system's ready statuses --> job[Ready to invoice]
job --> rules{Does an invoice rule match?}
rules -- yes --> wait[Waits: the job lists the rules]
rules -- no --> draft[Flow draft invoice]
draft --> check[A person checks it in Flow]
check --> mode{Send mode}
mode -- accounting_draft --> xdraft[Xero draft]
xdraft --> xapprove[A person approves and sends it in Xero]
mode -- approve_and_email --> xauth[Xero approved invoice]
xauth --> xemail[Xero emails it to the customer]
xapprove --> back[The mirror reads it back to Flow]
xemail --> back
- Ready. A job is in work until it is ready to invoice. Ready is Flow's
own stage, not a work system status. A person marks a job ready on the
Jobs board, or an automation does it from the work system's status
(
docs/AUTOMATIONS.md). - Draft. The pipeline (
docs/JOB_INVOICE_LINKS.md) runs every two minutes. The automation "Draft when ready" drafts the invoice of each ready job that has no invoice and that no invoice rule stops. The draft waits in Flow. Nothing goes to Xero by itself. - Check. A person checks the draft in Flow and issues it. Issuing gives it its number and keeps the document as sent.
- Send. A person sends the issued invoice to Xero. The customer's send mode decides what Xero gets (below).
- Read back. The mirror (
docs/XERO.md, "The mirror") copies Xero's status. The matcher links the Xero invoice to the job by the Flow invoice that made it (flow_invoice). Approval, payment, void and credit notes then show on the job.
Reference
The Reference is the text the customer reads on the invoice, next to its
number. The lab writes it as a rule under Settings, Rules, Reference
(referenceTemplate), from tokens:
| Token | Value |
|---|---|
{practitioner} |
The job's practitioner. |
{patient} |
The patient name. The work system gives it only when its integration keeps patient names (Seazona: Settings, Integrations, Seazona, Keep patient names). |
The default rule is {practitioner} - {patient}. Text between two tokens
shows only when both have a value: with no patient name, the Reference is
the practitioner alone. An empty rule gives no Reference; the accounting
system then shows the invoice number. Flow never puts a work system's ids in
the Reference. The code is in server/core/references.js.
The automation "Reference from the rule" keeps the Reference of each draft made from a job up to date as the rule or the job's fields change. It never changes a Reference a person typed, and it does not change the draft's status. A job read before patient names were kept gets its name from one more read of the work system, at most 10 jobs each run.
The rules
The ledger's own checks guard every draft (server/core/ledger.js): the job
is not held, every line maps to a price item, it has a customer, the
accounting copy holds no invoice for it, and the work system's report is less
than a day old. Then the job must be marked ready to invoice.
Every other check is an invoice rule that the lab builds: When, If, Then
(docs/INVOICE_RULES.md). Flow makes starter rules from the earlier settings
once, for each organisation:
| Starter rule | If | Then | From the setting |
|---|---|---|---|
| Customer not billable | Customer is billable is no | Never draft | customer billable |
| No amount | Job total is at most 0 | Wait for a person | |
| Old job | Job age (days) is more than 90 | Wait for a person | staleDays |
| Practitioner required | Practitioner is empty | Wait for a person (off until turned on) | requirePractitioner |
| Rush charge share | Rush line share is not 20% | Wait for a person | rushItemCode, rushPercent (only when a code is set) |
The earlier lab app held these checks in its code. In Flow they are rows the
lab edits under Settings, Rules, Invoices. GET /api/invoicing/jobs lists the
rules each job without an invoice waits on (waitingFor).
staleDays still sets the matcher's hold on an old job that has no
accounting invoice (docs/JOB_INVOICE_LINKS.md). The settings
requirePractitioner, rushItemCode and rushPercent only seed the starter
rules.
A draft gets the invoice date when it is issued, and a due date
paymentTermsDays after the day Flow drafted it (default 30).
The automation "Draft when ready" turns the drafts on or off. It is on by
default. A customer's autoDraft turns them off for that customer. It runs
with or without an accounting integration. With no integrations on at all,
the pipeline does not run, and a person drafts from the Jobs board.
The duplicate check
The earlier app asked Xero for each job before it drafted. Flow does not. It drafts only when its own copy of Xero is complete, was read in the last day, and changed no later than the matcher's last check of the job, and holds no invoice with the job's own invoice number. When Flow sends an invoice it drafted that way, it skips Xero's live reference check too. An invoice a person made by hand in Flow still gets the live check.
Send modes
| Mode | In Flow | In Xero | Xero emails the customer |
|---|---|---|---|
accounting_draft (default) |
A person checks and sends | A draft. A person approves and sends it | When the person sends it in Xero |
approve_and_email |
A person approves (issues) and sends | Approved (AUTHORISED) |
Yes, at once, with the Xero template |
approve_and_email needs an email address on the Xero contact. The preview
says so when it has none.
Xero's email action is not idempotent: a repeat sends a second email. Flow
records the email as sending before it calls. It records sent, failed
(Xero refused) or unknown (no clear answer). Sending the invoice again
retries a failed email only. After unknown a person checks the invoice in
Xero.
Customer settings
Each customer can override some settings at
/api/invoicing/contacts/:id/billing. A null value takes the organisation's
setting.
| Setting | Meaning |
|---|---|
billable |
Rules never draft an invoice for a customer that is not billable |
defaultPractitioner |
The practitioner for jobs that name none |
autoDraft |
Drafts on or off for this customer |
sendMode |
The send mode for this customer |
paymentTermsDays |
The customer's payment terms |