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

Translates a processor subscription response into local Ecto changesets.

A "projection" in Accrue means decomposing a processor subscription
response into a flat attrs map that `Accrue.Billing.Subscription`
accepts. This module handles type coercions, provider-specific lifecycle
fields, and `data` normalization for round-trip safety.

Handles both the atom-keyed shape produced by `Accrue.Processor.Fake`
and the string-keyed shape produced by remote adapters. Callers may pass
`processor: :stripe | :paddle | ...` to force a specific projection mode;
otherwise the configured processor name is used.

# `decompose`

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

# `to_string_keys`

```elixir
@spec to_string_keys(term()) :: term()
```

Recursively converts atom-keyed maps to string-keyed maps and
DateTimes to ISO8601 strings so the result is jsonb round-trip safe.

Public so `Accrue.Billing.InvoiceProjection` can reuse the same
normalization rather than storing atom-keyed data and getting shape
drift on reload.

---

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