> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wellapp.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Journal

> A Journal (record root: `journals`) represents a named accounting book used to categorize and post financial entries within a workspace — for example, a Sales j

A Journal (record root: `journals`) represents a named accounting book used to categorize and post financial entries within a workspace — for example, a Sales journal, a Bank journal, or a Miscellaneous journal. It is the top-level organizational unit for double-entry bookkeeping, grouping JournalEntry records beneath it, and optionally carrying default debit/credit LedgerAccount references to pre-fill lines on new entries. Journals are workspace-scoped, soft-deleted, and provisioned either manually or by the financial-pipeline sync (via `sourceWorkspaceConnector`); the `source_entity_id` field is the stable provider-side identifier used for idempotent upserts during sync.

| Naming                          | Value          |
| ------------------------------- | -------------- |
| Object                          | Journal        |
| Resource type (JSON:API `type`) | `journal`      |
| Collection / records root       | `journals`     |
| REST base                       | `/v1/journals` |
| Entity class                    | `Journal`      |

## API operations

| Operation | Method & path              | Status        |
| --------- | -------------------------- | ------------- |
| List      | `GET /v1/journals`         | ✅ Implemented |
| Retrieve  | `GET /v1/journals/{id}`    | ✅ Implemented |
| Create    | `POST /v1/journals`        | 🟡 Planned    |
| Update    | `PATCH /v1/journals/{id}`  | 🟡 Planned    |
| Delete    | `DELETE /v1/journals/{id}` | 🟡 Planned    |

## Data model

### Attributes

| Field              | Type                       | Required | Constraints                                                                                                                                                                                                                                                                                    | Allowed values                                 | Description                                                                                                                                                                                                           |
| ------------------ | -------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| journal\_id        | string, UUID, 🔒 system    | ✅ Yes    | UNIQUE; generated via gen\_random\_uuid() on insert                                                                                                                                                                                                                                            | —                                              | Public stable identifier for the journal, exposed in all API responses. Generated server-side; never writable by the client.                                                                                          |
| code               | string                     | ✅ Yes    | max length 10; UNIQUE(workspace\_pk, code) — plain unique constraint on all rows including soft-deleted ones, enforced at the database level; mirrored by @Unique(\{ properties: \['workspace', 'code'] }) on the entity                                                                       | —                                              | Short alphanumeric book code assigned by the workspace or imported from the accounting provider (e.g. 'VT' for sales, 'BQ' for bank, 'OD' for miscellaneous). Must be unique per workspace across all rows.           |
| name               | string                     | ✅ Yes    | max length 255                                                                                                                                                                                                                                                                                 | —                                              | Human-readable display label for the journal (e.g. 'Ventes — Clients France', 'Banque Qonto EUR').                                                                                                                    |
| journal\_type      | enum (journal\_type\_enum) | ✅ Yes    | NOT NULL; mapped to PostgreSQL native enum journal\_type\_enum                                                                                                                                                                                                                                 | BANK, SALES, PURCHASES, MISC, OPENING, CLOSING | Accounting classification of the journal. BANK: cash/bank movement book. SALES: receivables and revenue. PURCHASES: payables and expenses. MISC: catch-all for adjustments. OPENING/CLOSING: period-boundary entries. |
| source\_entity\_id | string                     | ⚪ No     | nullable; max length 255 (varchar(255) in DDL); PARTIAL UNIQUE INDEX journals\_workspace\_source\_entity\_id\_unique on (workspace\_pk, source\_entity\_id) WHERE source\_entity\_id IS NOT NULL AND deleted\_at IS NULL — ensures idempotent upserts per provider without conflicting on NULL | —                                              | Stable identifier assigned by the originating financial provider (e.g. Pennylane journal ID). Used by the sync pipeline for deduplication/upsert. NULL for manually created journals.                                 |
| is\_active         | boolean                    | ✅ Yes    | DEFAULT true; indexed (idx\_journals\_is\_active)                                                                                                                                                                                                                                              | true, false                                    | Whether the journal is currently in use. Inactive journals are hidden from accounting entry creation flows but remain queryable for historical reporting.                                                             |
| created\_at        | Date, 🔒 system            | ✅ Yes    | NOT NULL DEFAULT now(); set once via MikroORM onCreate lifecycle hook; not writable by client                                                                                                                                                                                                  | —                                              | ISO 8601 timestamp of record creation.                                                                                                                                                                                |
| updated\_at        | Date, 🔒 system            | ✅ Yes    | NOT NULL DEFAULT now(); set via MikroORM onCreate + onUpdate lifecycle hooks; not writable by client                                                                                                                                                                                           | —                                              | ISO 8601 timestamp of the last modification. Always set at insert time via DEFAULT now(); refreshed on every ORM flush that touches this entity.                                                                      |
| deleted\_at        | Date                       | ⚪ No     | nullable; soft-delete sentinel — all active queries must predicate deleted\_at IS NULL                                                                                                                                                                                                         | —                                              | ISO 8601 timestamp set when the journal is soft-deleted. NULL means the record is active. Hard deletes are not supported.                                                                                             |

### Relationships

| Name                         | Type                          | Required | Description                                                                                                                                                                                                                                                                          |
| ---------------------------- | ----------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| workspace                    | to-one (workspace)            | ✅ Yes    | The tenant workspace that owns this journal. All queries must scope to the authenticated workspace; the combination (workspace\_pk, code) carries a plain UNIQUE constraint enforcing per-workspace code uniqueness. References core\_api.workspaces.                                |
| default\_debit\_account      | to-one (ledger\_account)      | ⚪ No     | Optional default LedgerAccount pre-filled as the debit leg when creating new JournalEntry lines under this journal. Indexed (idx\_journals\_default\_debit\_account). References core\_api.ledger\_accounts.                                                                         |
| default\_credit\_account     | to-one (ledger\_account)      | ⚪ No     | Optional default LedgerAccount pre-filled as the credit leg when creating new JournalEntry lines under this journal. References core\_api.ledger\_accounts.                                                                                                                          |
| source\_workspace\_connector | to-one (workspace\_connector) | ⚪ No     | The WorkspaceConnector sync instance that created or last reconciled this journal record. NULL for manually created journals. Used for provenance tracking and to identify connector-managed records that should not be edited manually. References core\_api.workspace\_connectors. |

### System-computed

* `journal_id` is generated server-side via PostgreSQL `gen_random_uuid()` (defaultRaw) and mirrored in the ORM entity initializer `randomUUID()`. Never supplied by the client.
* `created_at` is set once by the MikroORM `onCreate` lifecycle hook at insert time. The database column is NOT NULL DEFAULT now(). Not writable by the client.
* `updated_at` is set by both `onCreate` and `onUpdate` MikroORM lifecycle hooks. The database column is NOT NULL DEFAULT now(), so it is always populated from the moment of insert. Reflects the timestamp of the last ORM flush touching this entity.
* `deleted_at` is null on active records. Set to the current timestamp on soft-delete. All repository queries must include `deleted_at: null` as a filter predicate.
* The combination `(workspace_pk, code)` carries a plain database-level UNIQUE constraint (defined in the DDL as `UNIQUE(workspace_pk, code)` and mirrored by `@Unique({ properties: ['workspace', 'code'] })` on the entity). This constraint applies to all rows, including soft-deleted ones.
* `source_entity_id` carries a PARTIAL UNIQUE INDEX `journals_workspace_source_entity_id_unique` on `(workspace_pk, source_entity_id) WHERE source_entity_id IS NOT NULL AND deleted_at IS NULL`. This enables idempotent upserts by the financial sync pipeline without conflicting on NULL values for manually created journals.
* `sourceWorkspaceConnector` (→ `source_workspace_connector_pk` FK column) is set by the ingestion pipeline when a journal is created via connector sync (e.g. Pennylane). NULL indicates manual creation. Presence signals that the record is pipeline-owned and should not be edited without understanding sync implications. A partial index `idx_journals_source_wc` on `(source_workspace_connector_pk) WHERE source_workspace_connector_pk IS NOT NULL` supports provenance queries.
* Journals are reachable from a Company via the Hasura computed field `company_journals(company_row, hasura_session)`, which traverses the 3-hop path: `companies → journal_entry_lines (company_pk) → journal_entries (journal_entry_pk) → journals (journal_pk)`. No direct `company_pk` FK exists on the `journals` table itself.
* `is_active` defaults to `true` at creation. The pipeline or a workspace admin may flip it to `false` to retire a journal while preserving historical entries.

## Example

```json theme={null}
{
  "data": {
    "type": "journal",
    "id": "a3f1c2d4-7e8b-4a9c-b5f6-0d1e2f3a4b5c",
    "attributes": {
      "journal_id": "a3f1c2d4-7e8b-4a9c-b5f6-0d1e2f3a4b5c",
      "code": "VT",
      "name": "Ventes — Clients France",
      "journal_type": "SALES",
      "source_entity_id": "pnl_jnl_00042",
      "is_active": true,
      "created_at": "2026-01-15T09:23:11.000Z",
      "updated_at": "2026-03-04T14:07:55.000Z",
      "deleted_at": null
    },
    "relationships": {
      "workspace": {
        "data": { "type": "workspace", "id": "d5e6f7a8-b9c0-4d1e-a2f3-b4c5d6e7f8a9" }
      },
      "default_debit_account": {
        "data": { "type": "ledger_account", "id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e" }
      },
      "default_credit_account": {
        "data": { "type": "ledger_account", "id": "c2d3e4f5-a6b7-4c8d-9e0f-1a2b3c4d5e6f" }
      },
      "source_workspace_connector": {
        "data": { "type": "workspace_connector", "id": "e3f4a5b6-c7d8-4e9f-a0b1-c2d3e4f5a6b7" }
      }
    }
  }
}
```

<sub>Source: `apps/api/src/database/entities/Journal.ts` · domain: financial-graph · tier: Main</sub>
