Invoices
What it is
Accounts receivable for the entity you currently have selected: every invoice, what is still owed on it, and the tools to chase it. Switching entity reloads the list.
Four tabs:
- 📄 Receivables — the invoice list, described below.
- 📠 SOA Generator — a signpost only, with a Launch SOA Tool ↗ link to
/soa. - 💸 Business Expenses — a signpost only, with a Manage Expenses ↗ link to
/accounting/expenses. - 🔁 Recurring — the real recurring-invoice screen, loaded in place.
🔴 Money is never converted or summed across currencies. A USD invoice reads in USD and an INR one in INR, and the Outstanding and Overdue tiles show one line per currency rather than a single total. This is deliberate (owner decision, 2026-08-19). Conversion to a single reporting currency exists only in the accounting/Tally export.
Who can open it
Any signed-in staff account that is active. Two gates, both in proxy.ts: account status, then
the finance.invoices feature grant while FEATURE_GRANULAR_RBAC is on, with the owner bypassing.
There is no role restriction beyond that.
Before you start
-
The status shown is worked out, not stored. It comes from the balance and the customer's payment terms (30 days when the customer has none set):
Shown Means Wired (Pending) Money has been wired but the balance is not yet clear. Paid Nothing outstanding. Overdue Nd Past the customer's terms, by N days. Partial Something has been paid, still within terms. Unpaid Nothing paid, still within terms. Changing a customer's payment terms therefore changes what looks overdue.
-
Deleting an invoice also deletes its credit notes. It is a cascade, and it is permanent.
Every control on the page
Header: ⋯ More with Export CSV, Print, Archive selected and Bulk-tag. Only Print works — see "Partly built".
Above the list:
| Control | What it does |
|---|---|
| ⚡ Reconcile Payment | Opens reconciliation: apply one received payment across several invoices for a customer. |
| + Log Invoice | Opens the invoice form. It becomes ✕ Cancel while the form is open. |
| Four tiles | Outstanding and Overdue (one line per currency), Total Invoices, Avg Days to Pay. |
| Search | Invoice number or vessel. |
| all / unpaid / paid / overdue | Status chips, written into the address bar so a filtered list can be shared. A fifth filter, weekly, exists but has no button — reach it with ?filter=weekly. |
| Filters | ⚠️ Applies nothing — see "Partly built". Saved Views and the pinned saved filter inside it do work. |
| Columns | Number, Client, Status, Date, Amount, Balance, Currency, Entity, ePOD Status, Overdue Days. Remembered; Reset restores the default six. |
Tick rows and the bulk bar offers 📤 Send Invoice, ✓ Mark Paid, 📧 Send Reminders, ⬇ Export CSV, ⬇ Tally XML, and 🗑 Delete.
⚠️ Tally XML here is the only place that records an invoice as exported to Tally. The single-invoice export on the detail screen does not — in fact it is not on that screen at all (see "Partly built").
The table — invoice number, customer, status, dates and balance, with inline editing of vessel, invoice date, due date and status, a record payment action, delete, and paging.
⚠️ Inline edits here have no concurrency guard. Unlike the invoice editor, editing a status or a due date in this list will overwrite whatever someone else changed a moment earlier without warning. This is A2Z-F227, PARTIALLY IMPLEMENTED in the inventory: "no concurrency guard; divergent from F226".
Prefilled from elsewhere. Arriving with ?quote= or ?po= opens the invoice form already
filled from that quotation or purchase order. That is what Convert to Invoice on a quotation
does.
Partly built — do not rely on these
- ⋯ More → Export CSV, Archive selected and Bulk-tag do nothing. Only Print works. Use the bulk bar's Export CSV instead, which does.
- The Filters panel applies nothing. The chips are the real filter.
- 🔴 The two suggestion-bar buttons are placeholders. On the overdue filter, Tactical Intervention: Risk Mitigation → Batch Reminders only pops up "Launching Batch Reminder Sequence..." and sends nothing. On the weekly filter, Cash Flow Optimization → Confirm Receipts only pops up "Confirming expected settlements..." and confirms nothing. To send reminders for real, tick the invoices and use 📧 Send Reminders in the bulk bar.
What it writes
| Action | What it writes |
|---|---|
| Inline vessel / invoice date | Updates invoices directly, with no concurrency guard. |
| Inline due date / status | PATCH /api/invoices/[id], also unguarded. |
| 📤 Send Invoice (bulk) | POST /api/invoices/bulk — emails each invoice to its customer. |
| ✓ Mark Paid (bulk) | POST /api/invoices/bulk. |
| 📧 Send Reminders (bulk) | POST /api/invoices/bulk-reminder — the real reminder path. |
| ⬇ Tally XML (bulk) | Exports the vouchers and stamps tally_synced_at — the only surface that does. |
| ⬇ Export CSV (bulk) | Downloads; writes nothing. |
| 🗑 Delete | Deletes the invoices and their credit notes. Permanent. |
| ⚡ Reconcile Payment | Records the payment across the invoices you allocate it to. |
| + Log Invoice | Creates the invoice and its items. |
When it goes wrong
An invoice you expect is missing. Check the entity selector first, then the status chip.
The Outstanding tile shows several lines. That is correct — one line per currency, never summed.
An invoice looks overdue when it should not. The calculation uses the customer's payment terms, defaulting to 30 days. Fix the terms on the customer record.
Batch Reminders did nothing. It is a placeholder. Tick the invoices and use 📧 Send Reminders.
Your inline edit was silently overwritten. There is no concurrency guard on this list. For anything that must not be lost, edit from the invoice's own edit screen, which does guard.
⋯ More → Export CSV did nothing. Use the bulk bar's Export CSV.
Related screens
- Invoices — Id — one invoice: send, export, generate downstream documents.
- Invoices — Id Edit — amend the invoice's lines, with a concurrency guard.
- Invoices — Recurring — the 🔁 Recurring tab on its own route.
- Quotations — where Convert to Invoice starts.