# `Logistiki.Accounting`
[🔗](https://github.com/thanos/logistiki/blob/v0.1.0/lib/logistiki/accounting/context.ex#L1)

The context for internal accounting artifacts: journals and postings.

Applications should normally publish business events (`Logistiki.process/1`)
rather than calling these functions directly. The functions here are exposed
for tests, migration, support tools, and controlled administrative
operations.

# `draft_journal`

Administrative helper to build a draft journal directly from attrs (for tests,
migration, and support tools). Not the normal application-facing API.

# `get_journal`
*since 0.1.0* 

Fetches a journal by id.

## Arguments

  * `id` — `integer()` — the journal primary key.

## Returns

  * `{:ok, %Journal{}}` — the journal with postings preloaded.
  * `{:error, :not_found}` — no journal with that id.

## Examples

    iex> {:ok, journal} = Logistiki.Accounting.get_journal(1)
    iex> journal.status
    "posted"
    iex> {:error, :not_found} = Logistiki.Accounting.get_journal(999)

# `get_journal!`
*since 0.1.0* 

Fetches a journal by id, raising if not found.

## Arguments

  * `id` — `integer()` — the journal primary key.

## Returns

  * `%Journal{}` — the journal with postings preloaded. Raises
    `Ecto.NoResultsError` if not found.

## Examples

    iex> journal = Logistiki.Accounting.get_journal!(1)
    iex> journal.status
    "posted"
    iex> journal.postings
    [%Posting{...}, %Posting{...}]

# `list_journals`
*since 0.1.0* 

Lists journals, optionally filtered, with postings preloaded.

## Arguments

  * `opts` — `keyword()` of options:
      * `:status` — `String.t` — e.g. `"posted"`, `"draft"`, `"reversed"`
      * `:event_id` — `String.t` — filter by originating event id

## Returns

  * `[Journal.t()]` — ordered by `inserted_at` descending, with `:postings`
    preloaded. Empty list if none match.

## Examples

    iex> Logistiki.Accounting.list_journals(status: "posted")
    [%Journal{status: "posted", postings: [%Posting{...}, ...]}, ...]

    iex> Logistiki.Accounting.list_journals(event_id: "evt_001")
    [%Journal{event_id: "evt_001", ...}]

# `list_postings`
*since 0.1.0* 

Lists postings for `journal`, ordered by sequence.

## Arguments

  * `journal` — `%Journal{}` — the journal whose postings to list.

## Returns

  * `[Posting.t()]` — ordered by `sequence` ascending.

## Examples

    iex> Logistiki.Accounting.list_postings(journal)
    [%Posting{sequence: 1, ...}, %Posting{sequence: 2, ...}]

# `post_journal`
*since 0.1.0* 

Posts a draft journal and its postings.

Validates the full invariant set, resolves `virtual_account_id` for each
posting from its `account_code`, then inserts the journal (status `posted`)
and its postings in a single transaction.

Returns `{:ok, posted_journal}` or `{:error, %Logistiki.Error{}}`.

# `reverse_journal`

Reverses a posted journal by creating a new posted reversal journal that
exactly negates the original postings, and marks the original `reversed`.

Returns `{:ok, reversal_journal}` or `{:error, %Logistiki.Error{}}`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
