| 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. |