# `PhoenixKitBilling.Activity`
[🔗](https://github.com/BeamLabEU/phoenix_kit_billing/blob/0.5.1/lib/phoenix_kit_billing/activity.ex#L1)

Thin wrapper around `PhoenixKit.Activity.log/1` for the billing module.

Centralizes the `Code.ensure_loaded?/1` guard, the rescue clause, and
the default metadata (`module: "billing"`, `actor_role`) so every LV
call site stays consistent and **logging failures never crash the
caller**.

## Where to call this

Activity logging happens at the **LiveView layer**, on the `{:ok, _}`
branch of each successful mutation — never inside context functions.
The LiveView is where the actor is unambiguously known (via
`socket.assigns[:phoenix_kit_current_scope]`) and where user intent is
clear ("admin clicked Save"). Context functions stay pure and keep
stable signatures.

## Action strings

Actions follow `"billing.<resource>_<verb>"`, e.g.
`"billing.order_created"`, `"billing.invoice_voided"`.

## PII safety

Only ever pass PII-safe metadata: resource uuids, status strings,
amounts, currency codes, order/invoice numbers, counts. **Never** log
email, phone, person names, card data, tokens, or free text.

# `log_result`

```elixir
@type log_result() :: :ok | :activity_unavailable | {:ok, struct()} | {:error, any()}
```

Return value of `log/2`. Mirrors `PhoenixKit.Activity.log/1` plus the unavailable/rescued sentinels.

# `actor_role`

```elixir
@spec actor_role(Phoenix.LiveView.Socket.t()) :: String.t() | nil
```

Extracts the acting user's primary role-name string from the socket's
scope (first entry of `cached_roles`). Returns `nil` when no role is
cached. Role names are not PII.

# `actor_uuid`

```elixir
@spec actor_uuid(Phoenix.LiveView.Socket.t()) :: String.t() | nil
```

Extracts the acting user's uuid from the LiveView socket assigns.

Reads `socket.assigns[:phoenix_kit_current_scope]` (the billing
convention; the production `live_session :phoenix_kit_admin` on_mount
hook populates it). Returns `nil` for an unauthenticated/absent scope.

# `log`

```elixir
@spec log(
  String.t(),
  keyword()
) :: log_result()
```

Logs a billing activity entry via `PhoenixKit.Activity`.

No-ops (returns `:activity_unavailable`) when core's `PhoenixKit.Activity`
module isn't loaded, and rescues/catches any failure so the calling
LiveView event handler can't crash on a logging error.

## Options

  * `:actor_uuid` — uuid of the acting user (use `actor_uuid/1`)
  * `:actor_role` — role-name string of the actor (use `actor_role/1`)
  * `:mode` — defaults to `"manual"`
  * `:resource_type` — e.g. `"order"`, `"invoice"`, `"currency"`
  * `:resource_uuid` — uuid of the mutated record
  * `:target_uuid` — second-party uuid where applicable
  * `:metadata` — extra PII-safe metadata map (merged over defaults)

---

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