The canonical, flattened representation of a business event.
The knowledge layer generates facts from this struct. Not every event populates every field.
Fields
id—String.t() | nil— the event id (e.g."evt_001")type—String.t()— the event type (e.g."deposit_received")source_system—String.t() | nil— e.g."bank_core"source_id—String.t() | nil— e.g."wire_123"actor_id—String.t() | niloccurred_at—DateTime.t() | nileffective_date—Date.t() | nilamount—Decimal.t() | nil— e.g.Decimal.new("1000.00")currency—String.t() | nil— e.g."USD"entity_id—String.t() | nilaccount_id—String.t() | nilaccount_code—String.t() | nil— e.g."LIABILITIES:CLIENT_DEPOSITS:USD:ACME:OPERATING"cash_account_code—String.t() | nilfee_income_account_code—String.t() | nilinterest_expense_account_code—String.t() | nildestination_account_code—String.t() | nilcounterparty_account_code—String.t() | nilcounterparty_id—String.t() | nilproduct_code—String.t() | niljurisdiction—String.t() | nilfee_type—String.t() | nil— e.g."wire_fee"entity_type—String.t() | nil— e.g."corporate","individual"has_accounting_impact—boolean()— defaulttrue;falsefor events likeAccountOpenedmetadata—map()— default%{}
Example
%Logistiki.Event.Normalized{
id: "evt_001",
type: "deposit_received",
amount: Decimal.new("1000.00"),
currency: "USD",
account_code: "LIABILITIES:CLIENT_DEPOSITS:USD:ACME:OPERATING",
cash_account_code: "ASSETS:CASH:USD:NOSTRO",
entity_type: "corporate",
effective_date: ~D[2026-07-07]
}
Summary
Functions
Builds a normalized event from a keyword/map of fields.
Converts the normalized event into a plain string-keyed map suitable for persistence (JSONB columns) and audit records.
Types
@type t() :: %Logistiki.Event.Normalized{ account_code: String.t() | nil, account_id: String.t() | nil, actor_id: String.t() | nil, amount: Decimal.t() | nil, cash_account_code: String.t() | nil, counterparty_account_code: String.t() | nil, counterparty_id: String.t() | nil, currency: String.t() | nil, destination_account_code: String.t() | nil, effective_date: Date.t() | nil, entity_id: String.t() | nil, entity_type: String.t() | nil, fee_income_account_code: String.t() | nil, fee_type: String.t() | nil, has_accounting_impact: boolean(), id: String.t() | nil, interest_expense_account_code: String.t() | nil, jurisdiction: String.t() | nil, metadata: map(), occurred_at: DateTime.t() | nil, product_code: String.t() | nil, source_id: String.t() | nil, source_system: String.t() | nil, type: String.t() }
The canonical, flattened representation of a business event.
The knowledge layer generates facts from this struct. Not every event populates every field.
Fields
id—String.t() | nil— event id (e.g."evt_001")type—String.t()— event type (e.g."deposit_received","fee_assessed")source_system—String.t() | nil— e.g."bank_core","onboarding"source_id—String.t() | nil— e.g."wire_123"actor_id—String.t() | nil— e.g."user_789"occurred_at—DateTime.t() | nil— e.g.~U[2026-07-07 12:00:00Z]effective_date—Date.t() | nil— e.g.~D[2026-07-07]amount—Decimal.t() | nil— e.g.Decimal.new("1000.00")currency—String.t() | nil— e.g."USD","EUR"entity_id—String.t() | nil— e.g."1"account_id—String.t() | nil— e.g."10"account_code—String.t() | nil— e.g."LIABILITIES:CLIENT_DEPOSITS:USD:ACME:OPERATING"cash_account_code—String.t() | nil— e.g."ASSETS:CASH:USD:NOSTRO"fee_income_account_code—String.t() | nil— e.g."INCOME:FEES:WIRE"interest_expense_account_code—String.t() | nil— e.g."EXPENSES:INTEREST"destination_account_code—String.t() | nil— e.g."LIABILITIES:CLIENT_DEPOSITS:USD:ACME:PAYROLL"counterparty_account_code—String.t() | nil— e.g."LIABILITIES:CLIENT_DEPOSITS:USD:VENDOR"counterparty_id—String.t() | nil— e.g."5"product_code—String.t() | nil— e.g."retail_deposit"jurisdiction—String.t() | nil— e.g."US","EU"fee_type—String.t() | nil— e.g."wire_fee","monthly_fee"entity_type—String.t() | nil— e.g."corporate","individual"has_accounting_impact—boolean()— defaulttrue;falseforAccountOpenedmetadata—map()— default%{}
Example
%Logistiki.Event.Normalized{
id: "evt_001", type: "deposit_received",
amount: Decimal.new("1000.00"), currency: "USD",
account_code: "LIABILITIES:CLIENT_DEPOSITS:USD:ACME:OPERATING",
cash_account_code: "ASSETS:CASH:USD:NOSTRO",
entity_type: "corporate", effective_date: ~D[2026-07-07]
}
Functions
Builds a normalized event from a keyword/map of fields.
Arguments
attrs—keyword()ormap()of field names to values.
Returns
%Logistiki.Event.Normalized{}— the struct.
Examples
iex> Logistiki.Event.Normalized.new(%{id: "evt_1", type: "deposit_received", amount: Decimal.new("100")})
%Logistiki.Event.Normalized{id: "evt_1", type: "deposit_received", amount: Decimal.new("100"), ...}
Converts the normalized event into a plain string-keyed map suitable for persistence (JSONB columns) and audit records.
Decimal → string, DateTime → ISO 8601, Date → ISO 8601. Nil fields are
omitted.
Arguments
event—%Logistiki.Event.Normalized{}.
Returns
map()— string-keyed, with encoded values.
Examples
iex> Logistiki.Event.Normalized.to_map(%Logistiki.Event.Normalized{id: "evt_1", type: "deposit_received", amount: Decimal.new("1000.00")})
%{"id" => "evt_1", "type" => "deposit_received", "amount" => "1000.00", "has_accounting_impact" => true, "metadata" => %{}}