Journals and postings are internal accounting artifacts created by the runtime from business events. They may be exposed for audit, operations, support, import/export, and admin tooling, but applications should normally publish business events instead of creating journals directly.
Journals
Schema: journals
| field | type | notes |
|---|---|---|
id | bigint | PK |
event_id | string | the originating business event id |
external_id | string | |
source_system / source_type / source_id | string | provenance |
selected_policy | string | recorded for explanation/replay |
selected_template | string | recorded for explanation/replay |
description | string | |
status | string | draft, validated, posted, reversed, rejected |
effective_date | date | |
posted_at | utc_datetime | set when posted |
reversed_at | utc_datetime | set when reversed |
reversal_of_id | bigint | self-reference for reversals |
idempotency_key | string | unique; prevents duplicate posting |
explanation | map | the full knowledge-layer explanation |
metadata | map | |
inserted_at / updated_at | utc_datetime |
Rules
- posted journals are immutable
- rejected journals are preserved for audit
- reversals create a new journal that exactly negates the original postings
- the idempotency key prevents duplicate posting
- the selected policy/template are recorded for explanation and replay
Postings
Schema: postings
| field | type | notes |
|---|---|---|
id | bigint | PK |
journal_id | bigint | FK |
virtual_account_id | bigint | FK; resolved from account_code on insert |
account_code | string | denormalized for audit readability |
debit_credit | string | debit or credit |
amount | decimal(20,4) | always positive |
currency | string | |
memo | string | |
sequence | integer | ordering within the journal |
metadata | map | includes the symbolic role |
inserted_at / updated_at | utc_datetime |
Rules
- amount is positive; direction encodes sign
debit_creditisdebitorcredit- the posting account must be a leaf, active, posting-allowed account
- the journal must balance per currency (debits = credits)
- postings are immutable once the journal is posted
account_codeis denormalized for audit readability butvirtual_account_idremains canonical
Reversals
A reversal is a new posted journal whose postings flip the direction of the
original postings while keeping the amount, currency, account, and sequence.
Logistiki.Accounting.reverse_journal/2 validates that the reversal exactly
negates the original (InvariantValidator.validate_reversal/2), inserts the
reversal, and marks the original reversed. Both the original and the
reversal remain balance-counted (their postings net to zero).
Administrative API
Logistiki.Accounting.draft_journal(attrs) # admin/test helper
Logistiki.Accounting.post_journal(journal, postings)
Logistiki.Accounting.reverse_journal(journal, attrs \\ %{})
Logistiki.Accounting.get_journal!(id)
Logistiki.Accounting.list_journals(opts \\ [])
Logistiki.Accounting.list_postings(journal)These are useful for tests, migration, support tools, and controlled operations, but they are not the normal application-facing API.