# `Accrue.Billing.InvoiceActions`
[🔗](https://github.com/szTheory/accrue/blob/accrue-v1.0.0/lib/accrue/billing/invoice_actions.ex#L1)

Invoice write surface.

Exposes five user-path invoice actions on `Accrue.Billing` via a
`defdelegate` facade: `finalize_invoice`, `void_invoice`,
`pay_invoice`, `mark_uncollectible`, `send_invoice`.

Each action follows a consistent pattern: call the Stripe API, decompose
the response into local schema changes via `InvoiceProjection`, write
the updated invoice row and upsert its line items, and record an audit
event — all in a single database transaction.

`pay_invoice/2` returns an intent result (`{:ok, %Invoice{}}` or
`{:ok, :requires_action, pi}`) because Stripe may surface SCA/3DS.
The other four actions return plain `{:ok, %Invoice{}}`.
Every action has a bang variant that raises on `{:error, _}`;
`pay_invoice!/2` additionally raises `Accrue.ActionRequiredError` on
`:requires_action`.

The webhook path uses the force-status bypass on the Invoice schema —
that bypass is NOT reachable from this module. Illegal user-path
transitions (e.g. `draft -> paid`) are rejected by `Invoice.changeset/2`
with an error on `:status` and propagate as
`{:error, %Ecto.Changeset{}}`.

# `finalize_invoice`

```elixir
@spec finalize_invoice(
  Accrue.Billing.Invoice.t(),
  keyword()
) :: {:ok, Accrue.Billing.Invoice.t()} | {:error, term()}
```

# `finalize_invoice!`

```elixir
@spec finalize_invoice!(
  Accrue.Billing.Invoice.t(),
  keyword()
) :: Accrue.Billing.Invoice.t()
```

# `mark_uncollectible`

```elixir
@spec mark_uncollectible(
  Accrue.Billing.Invoice.t(),
  keyword()
) :: {:ok, Accrue.Billing.Invoice.t()} | {:error, term()}
```

# `mark_uncollectible!`

```elixir
@spec mark_uncollectible!(
  Accrue.Billing.Invoice.t(),
  keyword()
) :: Accrue.Billing.Invoice.t()
```

# `pay_invoice`

```elixir
@spec pay_invoice(
  Accrue.Billing.Invoice.t(),
  keyword()
) ::
  {:ok, Accrue.Billing.Invoice.t()}
  | {:ok, :requires_action, map()}
  | {:error, term()}
```

# `pay_invoice!`

```elixir
@spec pay_invoice!(
  Accrue.Billing.Invoice.t(),
  keyword()
) :: Accrue.Billing.Invoice.t()
```

# `send_invoice`

```elixir
@spec send_invoice(
  Accrue.Billing.Invoice.t(),
  keyword()
) :: {:ok, Accrue.Billing.Invoice.t()} | {:error, term()}
```

# `send_invoice!`

```elixir
@spec send_invoice!(
  Accrue.Billing.Invoice.t(),
  keyword()
) :: Accrue.Billing.Invoice.t()
```

# `void_invoice`

```elixir
@spec void_invoice(
  Accrue.Billing.Invoice.t(),
  keyword()
) :: {:ok, Accrue.Billing.Invoice.t()} | {:error, term()}
```

# `void_invoice!`

```elixir
@spec void_invoice!(
  Accrue.Billing.Invoice.t(),
  keyword()
) :: Accrue.Billing.Invoice.t()
```

---

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