Document Lifecycle
Documents are the centre of the data model: 103 fields, 42 relations, reaching 6 of the 8 schema clusters.documents is also the largest core domain — 56 files, 11,682 lines.
Creation paths
Four ways a document comes into existence, converging on the same accounting handoff. Number allocation happens before creation —batchAllocateNumbersActivity runs as a
distinct pipeline step so numbers stay gapless under concurrency.
Status model
STATUS_TYPE in the Prisma schema, with the documented meaning of each value:
CUSTOM is a ninth value — user-defined, and multiple are allowed per object type, so it
sits outside this graph.
Status resolution lives in the statuses domain (in-degree 4), not in documents.
Formats and e-invoicing
document-format is the third-largest core domain (24 files, 5,246 lines) — most of that
weight is the einvoice subtree. German e-invoicing (ZUGFeRD) goes through the mustang
domain, which wraps the Mustang toolchain and parses its validation report.
Delivery
Delivery snapshots format outputs rather than re-rendering on send — so what the customer received stays reproducible even if templates change later. Both portal token creation and auto-send run inside the ingestion pipeline as step 5.6 (chunk-processor.ts:478), so synced documents arrive delivery-ready.
Document connections
document_relations links documents in parent/child pairs — an invoice to its credit
note, an order to its invoice. It carries no org_id; tenancy comes only through
child_document_id and parent_document_id.
Resolution is a distinct pipeline step: resolveDocumentConnectionsActivity then
batchConnectDocumentsActivity (chunk-processor.ts:862,919).
Key files
Notes
gl-relevant-fields.ts is the coupling contract. It defines which document fields
force accounting re-derivation when changed — the reason documents and accounting
import each other. See Core Domain Map.
Edit eligibility is enforced in core, not the UI.
check-document-edit-eligibility.ts gates whether a document can still be modified once
it has accounting impact.
Sammelbeleg is a first-class creation path. The German collective-document flow has
its own creation function and its own API route (api/sammelbeleg).