Logistiki.Accounting.Journal (logistiki v0.1.0)

Copy Markdown View Source

A journal is an internal accounting artifact created by the runtime from a business event. Journals are not the main application-facing API; applications publish business events.

Statuses

  • draft — built but not yet posted
  • validated — passed invariant validation
  • posted — immutable, persisted, executed by the ledger backend
  • reversed — fully reversed by a later reversal journal
  • rejected — preserved for audit

Fields

  • idinteger() — primary key
  • event_idString.t() | nil — the originating business event id

  • external_idString.t() | nil

  • source_system / source_type / source_idString.t() | nil — provenance

  • selected_policyString.t() | nil — e.g. "cash_deposit"

  • selected_templateString.t() | nil

  • descriptionString.t() | nil

  • statusString.t() — one of statuses/0 (default "draft")
  • effective_dateDate.t() | nil

  • posted_atDateTime.t() | nil — set when posted

  • reversed_atDateTime.t() | nil — set when reversed

  • reversal_of_idinteger() | nil — self-reference for reversals

  • idempotency_keyString.t() | nil — unique; prevents duplicate posting

  • explanationmap() | nil — full knowledge-layer explanation

  • metadatamap()
  • postings[Posting.t()] — has_many association
  • inserted_at / updated_atDateTime.t()

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

Example

%Logistiki.Accounting.Journal{
  id: 1,
  event_id: "evt_001",
  selected_policy: "cash_deposit",
  status: "posted",
  effective_date: ~D[2026-07-07],
  posted_at: ~U[2026-07-07 12:00:00Z],
  idempotency_key: "evt:evt_001:policy:cash_deposit"
}

Summary

Types

t()

The Journal struct type — an internal accounting artifact created by the runtime from a business event.

Functions

True when the journal is posted (and therefore immutable).

True when the journal is a reversal of another journal.

Returns the list of allowed journal statuses as atoms.

Types

t()

@type t() :: %Logistiki.Accounting.Journal{
  __meta__: term(),
  description: String.t() | nil,
  effective_date: Date.t() | nil,
  event_id: String.t() | nil,
  explanation: map() | nil,
  external_id: String.t() | nil,
  id: integer() | nil,
  idempotency_key: String.t() | nil,
  inserted_at: DateTime.t() | nil,
  metadata: map() | nil,
  posted_at: DateTime.t() | nil,
  postings: [Logistiki.Accounting.Posting.t()] | Ecto.Association.NotLoaded.t(),
  reversal_of: term(),
  reversal_of_id: integer() | nil,
  reversed_at: DateTime.t() | nil,
  selected_policy: String.t() | nil,
  selected_template: String.t() | nil,
  source_id: String.t() | nil,
  source_system: String.t() | nil,
  source_type: String.t() | nil,
  status: String.t() | nil,
  updated_at: DateTime.t() | nil
}

The Journal struct type — an internal accounting artifact created by the runtime from a business event.

Fields

  • idinteger() | nil — primary key (e.g. 1)

  • event_idString.t() | nil — originating event id (e.g. "evt_001")

  • external_idString.t() | nil — external reference

  • source_systemString.t() | nil — e.g. "bank_core"

  • source_typeString.t() | nil — e.g. "deposit_received"

  • source_idString.t() | nil — e.g. "wire_123"

  • selected_policyString.t() | nil — e.g. "cash_deposit"

  • selected_templateString.t() | nil — e.g. "cash_deposit"

  • descriptionString.t() | nil — e.g. "deposit_received via cash_deposit"

  • statusString.t() | nil — e.g. "draft", "posted", "reversed"

  • effective_dateDate.t() | nil — e.g. ~D[2026-07-07]

  • posted_atDateTime.t() | nil — e.g. ~U[2026-07-07 12:00:00Z]

  • reversed_atDateTime.t() | nil

  • reversal_of_idinteger() | nil — self-reference for reversals

  • idempotency_keyString.t() | nil — unique duplicate-prevention key

  • explanationmap() | nil — full pipeline explanation

  • metadatamap() | nil — extensible metadata

  • postings[Posting.t()] | Ecto.Association.NotLoaded.t() — postings

  • inserted_atDateTime.t() | nil

  • updated_atDateTime.t() | nil

Example

%Logistiki.Accounting.Journal{
  id: 1, event_id: "evt_001", selected_policy: "cash_deposit",
  status: "posted", effective_date: ~D[2026-07-07]
}

Functions

posted?(arg1)

(since 0.1.0)
@spec posted?(t()) :: boolean()

True when the journal is posted (and therefore immutable).

Arguments

  • journal%__MODULE__{} or any term.

Returns

  • boolean()true only when status == "posted".

Examples

iex> Logistiki.Accounting.Journal.posted?(%Logistiki.Accounting.Journal{status: "posted"})
true
iex> Logistiki.Accounting.Journal.posted?(%Logistiki.Accounting.Journal{status: "draft"})
false

reversal?(arg1)

(since 0.1.0)
@spec reversal?(t()) :: boolean()

True when the journal is a reversal of another journal.

Arguments

  • journal%__MODULE__{} or any term.

Returns

  • boolean()true when reversal_of_id is not nil.

Examples

iex> Logistiki.Accounting.Journal.reversal?(%Logistiki.Accounting.Journal{reversal_of_id: 5})
true
iex> Logistiki.Accounting.Journal.reversal?(%Logistiki.Accounting.Journal{reversal_of_id: nil})
false

statuses()

(since 0.1.0)
@spec statuses() :: [atom(), ...]

Returns the list of allowed journal statuses as atoms.

Returns

  • [atom()][:draft, :validated, :posted, :reversed, :rejected]

Examples

iex> :posted in Logistiki.Accounting.Journal.statuses()
true