# `Accrue.Billing.MeterEvent`
[🔗](https://github.com/szTheory/accrue/blob/accrue-v0.3.0/lib/accrue/billing/meter_event.ex#L1)

Ecto schema for `accrue_meter_events` — the metered billing audit
ledger and transactional outbox.

One row per `Accrue.Billing.report_usage/3` call. Lifecycle:

  * `pending` — inserted inside `Repo.transact/2`, committed before
    Stripe is ever called.
  * `reported` — set after a successful processor call via the
    `Accrue.Processor.report_meter_event/1` callback.
    `reported_at` is stamped.
  * `failed` — set either synchronously (when the first Stripe call
    returns `{:error, _}`) or asynchronously (when Stripe emits a
    `v1.billing.meter.error_report_triggered` webhook).

The partial index `accrue_meter_events_failed_idx` on
`stripe_status = 'failed'` gives ops a free DLQ view.

Only derived error shapes are stored in `stripe_error :map` — never
the raw Stripe payload.

# `t`

```elixir
@type t() :: %Accrue.Billing.MeterEvent{
  __meta__: term(),
  customer: term(),
  customer_id: term(),
  event_name: term(),
  id: term(),
  identifier: term(),
  inserted_at: term(),
  occurred_at: term(),
  operation_id: term(),
  reported_at: term(),
  stripe_customer_id: term(),
  stripe_error: term(),
  stripe_status: term(),
  updated_at: term(),
  value: term()
}
```

# `failed_changeset`

```elixir
@spec failed_changeset(t(), term()) :: Ecto.Changeset.t()
```

Flips a row to `failed`, storing a sanitized error map in
`stripe_error`. Never stores the raw Stripe payload.

# `pending_changeset`

```elixir
@spec pending_changeset(map()) :: Ecto.Changeset.t()
```

Builds a changeset for inserting a `pending` meter-event row.

# `reported_changeset`

```elixir
@spec reported_changeset(t(), map()) :: Ecto.Changeset.t()
```

Flips a committed `pending` row to `reported`, stamping `reported_at`.
The Stripe event struct is accepted for symmetry but no fields are
pulled from it — the row already has everything we need.

---

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