# `Lotus.Viz`
[🔗](https://github.com/typhoonworks/lotus/blob/v0.16.6/lib/lotus/viz.ex#L1)

Service functions for managing query visualizations in Lotus storage.

- CRUD wrappers around `Lotus.Storage.QueryVisualization`
- Validation against a `%Lotus.Result{}` to ensure field references exist and
  numeric aggregations apply to numeric columns.

# `attrs`

```elixir
@type attrs() :: map()
```

# `id`

```elixir
@type id() :: integer() | binary()
```

# `create_visualization`

```elixir
@spec create_visualization(Lotus.Storage.Query.t() | id(), attrs()) ::
  {:ok, Lotus.Storage.QueryVisualization.t()} | {:error, Ecto.Changeset.t()}
```

# `delete_visualization`

```elixir
@spec delete_visualization(Lotus.Storage.QueryVisualization.t() | id()) ::
  {:ok, Lotus.Storage.QueryVisualization.t()} | {:error, Ecto.Changeset.t()}
```

# `list_visualizations`

```elixir
@spec list_visualizations(Lotus.Storage.Query.t() | id()) :: [
  Lotus.Storage.QueryVisualization.t()
]
```

# `update_visualization`

```elixir
@spec update_visualization(Lotus.Storage.QueryVisualization.t(), attrs()) ::
  {:ok, Lotus.Storage.QueryVisualization.t()} | {:error, Ecto.Changeset.t()}
```

# `validate_against_result`

```elixir
@spec validate_against_result(map(), Lotus.Result.t()) :: :ok | {:error, String.t()}
```

Validates a visualization config against a query result.

Checks:
- Referenced fields exist in `result.columns` for x, y, series, and filters
- Numeric aggregations (:sum, :avg) only apply to numeric columns

This does not persist anything; it is safe to call before `create_`/`update_`.

---

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