Motivation
immutable: true (merged earlier) makes a snapshot entity append-only - the STORAGE half of legal-grade documents. The remaining half: nothing POPULATES the snapshot declaratively. An issued document must freeze the counterparty/company data it was printed with; today prints dereference live master data, so editing a partner rewrites history on paper.
Proposal (discussion-first)
A declarative copy-on-event into the snapshot entity, in the postings/glue family:
snapshots:
- name: invoiceIssueSnapshot
on: { transitioned: Invoice, to: 3 } # the ISSUED transition
to: InvoiceSnapshot # immutable: true entity
map: { Invoice: id, partnerName: Partner.name, partnerTaxId: Partner.taxId, companyName: Company.legalName, ... }
Same event source as postings (-transitioned), same map semantics as generates, target saved once (idempotent by the source FK). The print template then prefers snapshot fields when present.
Why upstream
Every jurisdiction's audit practice expects issued documents to be frozen; the storage primitive exists, the population glue is the missing general-purpose piece.
Motivation
immutable: true(merged earlier) makes a snapshot entity append-only - the STORAGE half of legal-grade documents. The remaining half: nothing POPULATES the snapshot declaratively. An issued document must freeze the counterparty/company data it was printed with; today prints dereference live master data, so editing a partner rewrites history on paper.Proposal (discussion-first)
A declarative copy-on-event into the snapshot entity, in the postings/glue family:
Same event source as postings (
-transitioned), same map semantics as generates, target saved once (idempotent by the source FK). The print template then prefers snapshot fields when present.Why upstream
Every jurisdiction's audit practice expects issued documents to be frozen; the storage primitive exists, the population glue is the missing general-purpose piece.