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

Deterministic decomposition of a processor (Stripe- or Fake-shaped)
invoice into a flat attrs map ready for `Accrue.Billing.Invoice.changeset/2`
plus a list of per-line attrs ready for
`Accrue.Billing.InvoiceItem.changeset/2`.

Mirrors `Accrue.Billing.SubscriptionProjection` (D3-13..17): extracts
every D3-14 rollup column, converts unix-seconds timestamps to
`DateTime`, preserves the full upstream map in the `data` jsonb column,
and handles both string-keyed (Stripe wire shape via `Map.from_struct/1`)
and atom-keyed (`Accrue.Processor.Fake` state) inputs.

Used by both the user-path actions in `Accrue.Billing.InvoiceActions`
(Plan 05) and the webhook DefaultHandler reconcile path (Plan 07) so
that both code paths converge on identical rows.

# `decomposed`

```elixir
@type decomposed() :: %{invoice_attrs: map(), item_attrs: [map()]}
```

# `decompose`

```elixir
@spec decompose(map()) :: {:ok, decomposed()}
```

---

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