Skip to main content

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):

    ShownMeans
    Wired (Pending)Money has been wired but the balance is not yet clear.
    PaidNothing outstanding.
    Overdue NdPast the customer's terms, by N days.
    PartialSomething has been paid, still within terms.
    UnpaidNothing 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:

ControlWhat it does
⚡ Reconcile PaymentOpens reconciliation: apply one received payment across several invoices for a customer.
+ Log InvoiceOpens the invoice form. It becomes ✕ Cancel while the form is open.
Four tilesOutstanding and Overdue (one line per currency), Total Invoices, Avg Days to Pay.
SearchInvoice number or vessel.
all / unpaid / paid / overdueStatus 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.
ColumnsNumber, 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 MitigationBatch Reminders only pops up "Launching Batch Reminder Sequence..." and sends nothing. On the weekly filter, Cash Flow OptimizationConfirm 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

ActionWhat it writes
Inline vessel / invoice dateUpdates invoices directly, with no concurrency guard.
Inline due date / statusPATCH /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.
🗑 DeleteDeletes the invoices and their credit notes. Permanent.
⚡ Reconcile PaymentRecords the payment across the invoices you allocate it to.
+ Log InvoiceCreates 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.