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

Behaviour implemented by business events.

Applications publish business events. Logistiki decides whether and how those
events become accounting entries. An event must be able to report its type and
normalize itself into a `Logistiki.Event.Normalized` struct.

## Defining events

Use the `defevent` macro to declare a business event struct with the common
normalized fields and an automatic `Logistiki.Event` implementation:

    defmodule Logistiki.Event.DepositReceived do
      use Logistiki.Event, type: "deposit_received"

      defevent do
        field :cash_account_code, :string
      end
    end

## Common fields provided by `defevent`

Every event struct built with `defevent` includes: `id`, `source_system`,
`source_id`, `actor_id`, `occurred_at`, `effective_date`, `amount`,
`currency`, `entity_id`, `account_id`, `account_code`, `counterparty_id`,
`product_code`, `jurisdiction`, `entity_type`, `metadata`. Additional
event-specific fields are declared inside the `defevent do ... end` block.

## Dispatchers

`Logistiki.Event.event_type/1` and `Logistiki.Event.normalize/1` dispatch to
the event struct's implementation so callers don't need to know the module.

# `event_type`

```elixir
@callback event_type(struct :: term()) :: String.t()
```

Returns the string event type used by the knowledge layer.

## Callback arguments

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

## Returns

  * `String.t()` — e.g. `"deposit_received"`.

# `normalize`

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

Normalizes the event into a `Logistiki.Event.Normalized` struct.

## Callback arguments

  * `struct` — the event struct.

## Returns

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

# `__using__`
*macro* 

Injects the `Logistiki.Event` behaviour and the `event_type/1` implementation
into the calling module. Used with `use Logistiki.Event, type: "..."`.

## Options

  * `:type` — `String.t` — the event type string used by the knowledge layer
    (e.g. `"deposit_received"`, `"fee_assessed"`).

## Example

    use Logistiki.Event, type: "deposit_received"

# `defevent`
*since 0.1.0* *macro* 

Declares the event struct fields (beyond the common normalized fields) and
generates a `normalize/1` implementation that flattens the event into a
`Logistiki.Event.Normalized` struct.

## Arguments

  * `block` — a `do` block containing `Ecto.Schema.field/3` declarations for
    event-specific fields (e.g. `field :cash_account_code, :string`).

## Generated code

The macro builds an `embedded_schema` with the common fields plus any
declared fields, and a `normalize/1` function that constructs a
`%Logistiki.Event.Normalized{}` from the event struct, merging in any
extra event-specific fields (like `cash_account_code`).

## Example

    defevent do
      field :cash_account_code, :string
      field :fee_income_account_code, :string
    end

# `event_type`
*since 0.1.0* 

```elixir
@spec event_type(struct()) :: String.t()
```

Dispatches to the event struct's `event_type/1` implementation.

## Arguments

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

## Returns

  * `String.t()` — the event type (e.g. `"deposit_received"`).

## Examples

    iex> Logistiki.Event.event_type(%Logistiki.Event.DepositReceived{})
    "deposit_received"

# `normalize`
*since 0.1.0* 

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

Dispatches to the event struct's `normalize/1` implementation.

## Arguments

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

## Returns

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

## Examples

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

---

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