Skip to main content
Invoice is the core billing document entity in Well, representing receivable and payable documents (commercial invoices, credit notes, purchase orders, receipts, and related document types) extracted from uploaded files or ingested via connector syncs. It links two Company parties (issuer and receiver) within a Workspace, carries multi-currency financial totals with FX normalization, and tracks both a lifecycle status (draft → issued → paid → canceled) and an orthogonal payment dimension (payment_status) owned exclusively by the recompute service. Key associations include the source Document, line-item InvoiceItems, matched bank transactions via InvoiceTransaction pivot rows, payment instruments via InvoicePaymentMeans, and the originating WorkspaceConnector for provenance.

API operations

Data model

Attributes

Relationships

System-computed

  • invoice_id is generated automatically at insert by Postgres via defaultRaw: gen_random_uuid(). It is immutable after creation.
  • created_at is set once on INSERT via MikroORM onCreate: () => new Date() lifecycle hook.
  • updated_at is set on both INSERT and UPDATE via onCreate + onUpdate: () => new Date() lifecycle hooks. It is declared optional in the entity (updated_at?: Date) and may be absent on rows that have never been modified after creation.
  • deleted_at is null on creation and is set to a Date value by soft-delete logic. All active-row queries must predicate on deleted_at IS NULL. No hard delete should be issued directly.
  • payment_status (and paid_amount, balance_due, last_payment_allocation_date, override_version) are owned exclusively by the payment-recompute service. Application code and API clients must treat these as read-only. override_version is an optimistic concurrency counter incremented on every recompute write.
  • shadow_from_receipt defaults to false. It is set to true only by the mapReceiptToShadowFlat (R1) pipeline when synthesizing an invoice row from a payment_receipt document.
  • accounting_grand_total, accounting_items_total, accounting_tax_total, and accounting_currency are written by the invoice FX matching service (fx-rate.service.ts + invoice.service.ts) when the invoice local_currency differs from the workspace accounting currency.
  • source_workspace_connector (sourceWorkspaceConnector) is set at creation time when the invoice is ingested through a connector sync; it remains null for manually uploaded or email-extracted invoices.
  • Fields decorated with @Enrichable (issue_date, grand_total, local_currency, reference_number, terms, items_total, tax_total, description, invoice_number, due_date) are eligible for AI enrichment via the enrichment pipeline workers.
  • Partial index idx_invoices_workspace_invoice_number_active enforces uniqueness of (workspace_pk, invoice_number) among non-deleted rows where invoice_number IS NOT NULL, enabling efficient deduplication on import.
  • Partial index idx_invoices_workspace_source_connector_active on (workspace_pk, source_workspace_connector_pk) WHERE deleted_at IS NULL supports efficient tenant + connector listing queries.
  • Partial index idx_invoices_workspace_created_active on (workspace_pk, created_at DESC) WHERE deleted_at IS NULL mirrors the records-page default sort order to avoid full-table scans.

Example

Source: apps/api/src/database/entities/Invoice.ts · domain: financial-graph · tier: Main