JournalEntryLine

A Journal Entry Line (journal_entry_lines) is a single debit or credit leg within a double-entry journal entry. Each line is associated with exactly one JournalEntry and one primary LedgerAccount, carries a decimal debit or credit amount (never both simultaneously, enforced by a CHECK constraint), and may reference an auxiliary ledger account, a tax rate, and a counterparty company for subledger analysis. Lines are created exclusively by the accounting posting engine (invoice-journal-entry builder and payment-settlement pipeline) and are never written directly by end users.

NamingValue
ObjectJournalEntryLine
Resource type (JSON:API type)journal_entry_line
Collection / records rootโ€” (not a records root)
REST base/v1/journal-entry-lines
Entity classJournalEntryLine

Internal object. Not currently exposed on the public REST API. The operations below describe the intended contract.

API operations

OperationMethod & pathStatus
ListGET /v1/journal-entry-lines๐ŸŸก Planned
RetrieveGET /v1/journal-entry-lines/{id}๐ŸŸก Planned
CreatePOST /v1/journal-entry-lines๐ŸŸก Planned
UpdatePATCH /v1/journal-entry-lines/{id}๐ŸŸก Planned
DeleteDELETE /v1/journal-entry-lines/{id}๐ŸŸก Planned

Data model

Attributes

FieldTypeRequiredConstraintsAllowed valuesDescription
journal_entry_line_idstring (UUID)โœ… Yesuniqueโ€”Public stable identifier for the line, generated via gen_random_uuid() on creation. Used in all API and Hasura references.
labelstringโšช Nomax length 500โ€”Free-text description of the line (e.g. 'Revenue recognition โ€“ Invoice #INV-001'). Written by the posting engine from the source document.
debitdecimal(15,2)โœ… YesCHECK (debit >= 0), default '0'โ€”Debit amount in the workspace's functional currency. Defaults to 0. Cannot be positive simultaneously with credit (CHECK constraint on parent table: NOT (debit > 0 AND credit > 0)).
creditdecimal(15,2)โœ… YesCHECK (credit >= 0), default '0'โ€”Credit amount in the workspace's functional currency. Defaults to 0. Cannot be positive simultaneously with debit.
source_currencyenum (CurrencyCodeEnum)โšช Noโ€”USD, EUR, GBP, JPY, CHF, CAD, AUD, NZD โ€ฆ +18 moreISO 4217 currency code of the original transaction before conversion to the accounting currency. Populated when the source document is in a foreign currency.
source_amountdecimal(15,2)โšช Noโ€”โ€”The monetary amount expressed in source_currency before FX conversion. Null when source and accounting currencies are identical.
accounting_currencyenum (CurrencyCodeEnum)โšช Noโ€”Same set as source_currency โ€” full CurrencyCodeEnum value strings.ISO 4217 currency code used for the accounting books (the workspace's reporting currency). Populated during FX conversion.
accounting_amountdecimal(15,2)โšช Noโ€”โ€”The monetary amount converted to accounting_currency using the exchange rate at posting time.
lettering_codestringโšช Nomax length 20โ€”Reconciliation / lettering code used to match open AR/AP lines against their offsetting settlement lines. Assigned by the lettering engine.
lettering_datedateโšช Noโ€”โ€”Date on which the lettering code was assigned, marking when the outstanding balance was reconciled.
tax_ratedecimal(5,2)โšช NoCHECK (tax_rate >= 0 AND tax_rate <= 100)โ€”Inline tax rate percentage applied to this line (0โ€“100). Denormalised copy of the tax rate value at the time of posting, independent of any tax_rate_ref record.
posting_metadatajsonbโšช Noโ€”โ€”Arbitrary key-value payload attached by the posting engine for traceability (e.g. source invoice pk, posting run identifier). No enforced schema; consumers should treat as opaque.
cost_centerstringโšช Nomax length 100โ€”Analytic axis โ€” cost centre code for management reporting and budget allocation.
projectstringโšช Nomax length 100โ€”Analytic axis โ€” project identifier for project-based accounting or profitability tracking.
created_at๐Ÿ”’ system โ€” Dateโœ… Yesโ€”โ€”Timestamp set automatically when the record is first persisted. Never updated thereafter.
updated_at๐Ÿ”’ system โ€” Dateโšช Noโ€”โ€”Timestamp set on creation and refreshed on every update by the MikroORM onUpdate hook.
deleted_at๐Ÿ”’ system โ€” Date | nullโšช Noโ€”โ€”Soft-delete timestamp. Null means the record is active. Set by the posting engine or a cascade from the parent JournalEntry; never set directly by end users. All queries must filter deleted_at IS NULL.

Relationships

NameTypeRequiredDescription
workspaceto-one (ManyToOne)โœ… YesThe tenant boundary. Every journal entry line belongs to exactly one workspace. Indexed together with journal_entry (composite index) and with ledger_account (composite index).
journal_entryto-one (ManyToOne)โœ… YesThe parent double-entry journal entry this line belongs to. A journal entry must balance: the sum of all its lines' debits must equal the sum of all credits.
ledger_accountto-one (ManyToOne)โœ… YesThe primary chart-of-accounts ledger account credited or debited by this line (e.g. '401000 โ€“ Accounts Payable', '706000 โ€“ Revenue').
auxiliary_accountto-one (ManyToOne)โšช NoOptional subledger / auxiliary ledger account for detailed third-party tracking (e.g. a per-customer receivable subledger). References LedgerAccount.
companyto-one (ManyToOne)โšช NoThe counterparty company linked to this line for subledger analysis (e.g. the customer on an AR line or the supplier on an AP line). Populated by the posting engine from the source invoice's issuer or receiver.
tax_rate_refto-one (ManyToOne)โšช NoReference to the TaxRate record whose percentage was applied at posting time. Complements the denormalised tax_rate decimal field.

System-computed

  • journal_entry_line_id โ€” generated via gen_random_uuid() database default on INSERT; also seeded client-side by randomUUID() in the entity constructor.
  • created_at โ€” set to new Date() by MikroORM onCreate hook; never updated.
  • updated_at โ€” set to new Date() on onCreate and refreshed by MikroORM onUpdate hook on every flush.
  • deleted_at โ€” null on creation; set to a timestamp by soft-delete logic in the accounting posting engine or by cascade from the parent JournalEntry; never hard-deleted in normal operation.
  • debit / credit defaults โ€” both default to '0' at the database level (DEFAULT 0) and in the entity constructor.
  • CHECK constraint chk_jel_debit_credit_exclusive โ€” enforced at the database level: NOT (debit > 0 AND credit > 0). A line must be either a debit line or a credit line, never both.
  • posting_metadata โ€” populated by the accounting posting engine (journal-entry-persister.service.ts / invoice-journal-entry-draft.builder.ts) with traceability data; not derived from any ORM hook.
  • accounting_currency / accounting_amount โ€” populated during FX conversion in the multi-currency posting path; null for same-currency workspaces.
  • Composite indexes: (workspace_pk, journal_entry_pk) and (ledger_account_pk, workspace_pk) are created by the Migration20260311100000 migration for query performance.

Example

{
  "data": {
    "type": "journal_entry_line",
    "id": "e3f1a2b4-5c6d-7e8f-9012-abcdef345678",
    "attributes": {
      "journal_entry_line_id": "e3f1a2b4-5c6d-7e8f-9012-abcdef345678",
      "label": "Invoice revenue recognition โ€“ Well App Inc",
      "debit": "0.00",
      "credit": "1250.00",
      "source_currency": "USD",
      "source_amount": "1250.00",
      "accounting_currency": "EUR",
      "accounting_amount": "1152.37",
      "lettering_code": "A001",
      "lettering_date": "2026-05-15",
      "tax_rate": "20.00",
      "posting_metadata": {
        "invoice_pk": 4821,
        "posting_run_id": "run_20260515_001"
      },
      "cost_center": "SALES-EU",
      "project": "Q2-2026-EXPANSION",
      "created_at": "2026-05-15T08:22:10.000Z",
      "updated_at": "2026-05-15T08:22:10.000Z",
      "deleted_at": null
    },
    "relationships": {
      "workspace": {
        "data": { "type": "workspace", "id": "wsp_9a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d" }
      },
      "journal_entry": {
        "data": { "type": "journal_entry", "id": "je_1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d" }
      },
      "ledger_account": {
        "data": { "type": "ledger_account", "id": "la_2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e" }
      },
      "auxiliary_account": {
        "data": null
      },
      "company": {
        "data": { "type": "company", "id": "cmp_3c4d5e6f-7a8b-9c0d-1e2f-3a4b5c6d7e8f" }
      },
      "tax_rate_ref": {
        "data": { "type": "tax_rate", "id": "tr_4d5e6f7a-8b9c-0d1e-2f3a-4b5c6d7e8f90" }
      }
    }
  }
}
Source: apps/api/src/database/entities/JournalEntryLine.ts ยท domain: financial-graph ยท tier: Supporting