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

The context for business events.

Persists, normalizes, and retrieves business events. Normalization dispatches
to the event struct's `Logistiki.Event` implementation.

## Normalization

`normalize/1` calls the event struct's `Logistiki.Event.normalize/1` callback
and returns a `%Logistiki.Event.Normalized{}` — the flattened representation
the knowledge layer consumes.

## Persistence

`persist/1` normalizes the event and inserts a `BusinessEvent` row with both
the raw `payload` (string-keyed map of the original struct) and the
`normalized_payload` (the flattened form). Status starts at `"normalized"`.

# `get_event!`
*since 0.1.0* 

```elixir
@spec get_event!(integer()) :: Logistiki.Events.BusinessEvent.t()
```

Fetches a persisted business event by id, raising if not found.

## Arguments

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

## Returns

  * `%BusinessEvent{}` — the persisted event. Raises `Ecto.NoResultsError` if not found.

## Examples

    iex> event = Logistiki.Events.get_event!(1)
    iex> event.event_type
    "deposit_received"

# `list_events`
*since 0.1.0* 

```elixir
@spec list_events(keyword()) :: [Logistiki.Events.BusinessEvent.t()]
```

Lists persisted business events, optionally filtered.

## Arguments

  * `opts` — `keyword()` of options:
      * `:event_type` — `String.t` — e.g. `"deposit_received"`
      * `:status` — `String.t` — e.g. `"processed"`, `"blocked"`

## Returns

  * `[BusinessEvent.t()]` — ordered by `inserted_at` descending. Empty list
    if none match.

## Examples

    iex> Logistiki.Events.list_events(status: "processed")
    [%BusinessEvent{event_type: "deposit_received", ...}]

    iex> Logistiki.Events.list_events(event_type: "fee_assessed")
    [%BusinessEvent{event_type: "fee_assessed", ...}]

# `normalize`
*since 0.1.0* 

```elixir
@spec normalize(struct()) :: {:ok, Logistiki.Event.Normalized.t()} | {:error, term()}
```

Normalizes a business event struct through its `Logistiki.Event`
implementation.

## Arguments

  * `struct` — a business event struct implementing `Logistiki.Event`.

## Returns

  * `{:ok, %Logistiki.Event.Normalized{}}` — the flattened event.
  * `{:error, term()}` — normalization failed.

## Examples

    iex> {:ok, normalized} = Logistiki.Events.normalize(%Logistiki.Event.DepositReceived{id: "evt_1"})
    iex> normalized.type
    "deposit_received"

# `persist`
*since 0.1.0* 

```elixir
@spec persist(struct()) ::
  {:ok, Logistiki.Events.BusinessEvent.t()} | {:error, term()}
```

Persists a raw business event struct along with its normalized form.

## Arguments

  * `struct` — a business event struct implementing `Logistiki.Event`
    (e.g. `%Logistiki.Event.DepositReceived{}`).

## Returns

  * `{:ok, %BusinessEvent{}}` — the persisted record (status `"normalized"`).
  * `{:error, term()}` — normalization or persistence failed.

## Examples

    iex> {:ok, persisted} = Logistiki.Events.persist(%Logistiki.Event.DepositReceived{
    ...>   id: "evt_001", amount: Decimal.new("1000.00"), currency: "USD", ...
    ...> })
    iex> persisted.event_type
    "deposit_received"
    iex> persisted.status
    "normalized"
    iex> persisted.normalized_payload["account_code"]
    "LIABILITIES:CLIENT_DEPOSITS:USD:ACME:OPERATING"

# `update_status`
*since 0.1.0* 

```elixir
@spec update_status(Logistiki.Events.BusinessEvent.t(), atom(), map() | nil) ::
  {:ok, Logistiki.Events.BusinessEvent.t()} | {:error, Ecto.Changeset.t()}
```

Updates the status of a persisted business event.

## Arguments

  * `event` — `%BusinessEvent{}` — the persisted event to update.
  * `status` — `atom()` — one of `BusinessEvent.statuses/0` (e.g.
    `:processed`, `:blocked`, `:no_accounting_impact`).
  * `explanation` — `map() | nil` — optional explanation (e.g.
    `%{reason: :blocked_by_rule}`).

## Returns

  * `{:ok, %BusinessEvent{}}` — the updated event.
  * `{:error, %Ecto.Changeset{}}` — validation failed.

## Examples

    iex> {:ok, updated} = Logistiki.Events.update_status(event, :processed)
    iex> updated.status
    "processed"

    iex> {:ok, updated} = Logistiki.Events.update_status(event, :blocked, %{reason: :sanctions})
    iex> updated.explanation
    %{reason: :sanctions}

---

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