# `PaperTiger.Store.PaymentMethods`
[🔗](https://github.com/EnaiaInc/paper_tiger/blob/v1.2.2/lib/paper_tiger/store/payment_methods.ex#L1)

ETS-backed storage for PaymentMethod resources.

Uses the shared store pattern via `use PaperTiger.Store` which provides:
- GenServer wraps ETS table
- Reads go directly to ETS (concurrent, fast)
- Writes go through GenServer (serialized, safe)

## Architecture

- **ETS Table**: `:paper_tiger_payment_methods` (public, read_concurrency: true)
- **GenServer**: Serializes writes, handles initialization
- **Shared Implementation**: All CRUD operations via PaperTiger.Store

## Examples

    # Direct read (no GenServer bottleneck)
    {:ok, payment_method} = PaperTiger.Store.PaymentMethods.get("pm_123")

    # Serialized write
    payment_method = %{id: "pm_123", customer: "cus_123", ...}
    {:ok, payment_method} = PaperTiger.Store.PaymentMethods.insert(payment_method)

    # Query helpers (direct ETS access)
    payment_methods = PaperTiger.Store.PaymentMethods.find_by_customer("cus_123")

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `clear`

```elixir
@spec clear() :: :ok
```

Clears all payment_methods from the store (all namespaces).

**Serialized write** - goes through GenServer.

Useful for test cleanup. Note: This clears ALL data, not just
the current namespace. For namespace-specific cleanup, use
`clear_namespace/1`.

# `clear_namespace`

```elixir
@spec clear_namespace(pid() | :global | {pid() | :global, String.t()}) :: :ok
```

Clears all payment_methods for a specific namespace.

Used by `PaperTiger.Test` to clean up after each test.

# `count`

```elixir
@spec count() :: non_neg_integer()
```

Counts total payment_methods in current namespace.

**Direct ETS access** - does not go through GenServer.

# `delete`

```elixir
@spec delete(String.t()) :: :ok
```

Deletes a payment_method from the store.

**Serialized write** - goes through GenServer.
Data is scoped to the current test namespace.

# `find_by_customer`

```elixir
@spec find_by_customer(String.t() | nil) :: [map()]
```

Finds payment methods by customer ID.

**Direct ETS access** - does not go through GenServer.
Returns empty list if customer_id is nil (Stripe requires customer param).

# `get`

```elixir
@spec get(String.t()) :: {:ok, map()} | {:error, :not_found}
@spec get(String.t()) :: {:ok, map()} | {:error, :not_found}
```

Retrieves a payment method by ID.

Overrides the default `get/1` to also check the global namespace
for pre-defined test tokens (pm_card_visa, pm_card_mastercard, etc.).

This allows tests running in isolated namespaces to use the standard
Stripe test tokens without explicitly creating them.

# `insert`

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

Inserts a payment_method into the store.

**Serialized write** - goes through GenServer to prevent race conditions.
Data is scoped to the current test namespace.

# `list`

```elixir
@spec list(keyword() | map()) :: PaperTiger.List.t()
```

Lists all payment_methods with optional pagination.

**Direct ETS access** - does not go through GenServer.
Data is scoped to the current test namespace.

## Options

- `:limit` - Number of items (default: 10, max: 100)
- `:starting_after` - Cursor for pagination
- `:ending_before` - Reverse cursor

# `list_namespace`

```elixir
@spec list_namespace(pid() | :global | {pid() | :global, String.t()}) :: [map()]
```

Returns all items in a specific namespace.

Useful for debugging test isolation.

# `prefix`

```elixir
@spec prefix() :: String.t() | nil
```

Returns the ID prefix for this resource.

# `start_link`

```elixir
@spec start_link(keyword()) :: GenServer.on_start()
```

Starts the payment_method store GenServer.

# `table_name`

```elixir
@spec table_name() :: atom()
```

Returns the ETS table name for this store.

# `update`

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

Updates a payment_method in the store.

**Serialized write** - goes through GenServer.
Data is scoped to the current test namespace.

---

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