# `Money.Ecto.Query.API`
[🔗](https://github.com/kipcole9/money_sql/blob/v2.0.0/lib/money/ecto/money_ecto_query_api.ex#L2)

Provides several helpers to query DB for the `Money` type.

### Usage

In a module where you wish to use these helpers, add:

    use Money.Ecto.Query.API

The default usage is designed to work with the `Money.Ecto.Composite.Type`
implementation for Postgres databases. Altenative impkmentations can be
made that comply with the `Money.Ecto.Query.API` behaviour. In that case

    use Money.Ecto.Query.API, adapter: MyAdapterModule

See the Adapters section below.

### Implementation

Under the hood it delegates to
[`Ecto.Query.API.fragment/1`](https://hexdocs.pm/ecto/Ecto.Query.API.html#fragment/1-defining-custom-functions-using-macros-and-fragment),
but might be helpful for compile-type sanity check for typos and
better language server support.

It is also designed to be an implementation-agnostic, meaning one can use
these helpers without a necessity to explicitly specify a backing type.

### Adapters

The default implementation recommends a `Composite` adapter, which is used by default.
To use it with, say, `MySQL`, one should implement this behaviour for `MySQL` and declare
the implementation as `use Money.Ecto.Query.API, adapter: MyImpl.MySQL.Adapter`

Although the library provides the MySQL adapter too (Money.Ecto.Query.API.Map.MySQL)
but it is not actively maintained, so use it on your own.

If for some reason you use `Map` type with `Postgres`, helpers are still available
with `use Money.Ecto.Query.API, adapter: Money.Ecto.Query.API.Map.Postgres`

# `amount`

```elixir
@macrocallback amount(Macro.t()) :: Macro.t()
```

Native implementation of how to retrieve `amount` from the DB.

For `Postgres`, it delegates to the function on the composite type,
  for other implementation it should return a `Ecto.Query.API.fragment/1`.

# `avg`

```elixir
@macrocallback avg(Macro.t()) :: Macro.t()
```

Native implementation of how to `avg` (average) several records having a field
of the type `Money` in the DB.

For `Postgres`, it delegates to the function on the composite type,
  for other implementation it should return a `Ecto.Query.API.fragment/1`.

# `cast_decimal`

```elixir
@callback cast_decimal(Decimal.t()) :: any()
```

Cast decimal to the value accepted by the database.

# `currency_code`

```elixir
@macrocallback currency_code(Macro.t()) :: Macro.t()
```

Native implementation of how to retrieve `currency_code` from the DB.

For `Postgres`, it delegates to the function on the composite type,
  for other implementation it should return a `Ecto.Query.API.fragment/1`.

# `sum`

```elixir
@macrocallback sum(Macro.t(), cast? :: boolean()) :: Macro.t()
```

Native implementation of how to `sum` several records having a field
of the type `Money` in the DB.

For `Postgres`, it delegates to the function on the composite type,
  for other implementation it should return a `Ecto.Query.API.fragment/1`.

# `amount_eq`
*macro* 

`Ecto.Query.API` helper, allowing to filter records having the same amount.

_Example:_

```elixir
iex> Organization
...> |> where([o], amount_eq(o.payroll, 100))
...> |> select([o], o.payroll)
...> |> Repo.all()
[Money.new(:EUR, "100"), Money.new(:USD, "100")
```

# `amount_ge`
*macro* 

`Ecto.Query.API` helper, allowing to filter records having the amount
greater than or equal to the one given as an argument.

_Example:_

```elixir
iex> Organization
...> |> where([o], amount_ge(o.payroll, 90))
...> |> select([o], o.payroll)
...> |> Repo.all()
[Money.new(:AUD, "90"), Money.new(:USD, "100")]
```

# `amount_in`
*macro* 

`Ecto.Query.API` helper, allowing to filter records having the amount
in the range given as an argument.

Accepts `[min, max]`, `{min. max}`, and `min..max` as a range.

_Example:_

```elixir
iex> Organization
...> |> where([o], amount_in(o.payroll, 90..110))
...> |> select([o], o.payroll)
...> |> Repo.all()
[Money.new(:EUR, "100"), Money.new(:USD, "100")]
```

# `amount_le`
*macro* 

`Ecto.Query.API` helper, allowing to filter records having the amount
less than or equal to the one given as an argument.

_Example:_

```elixir
iex> Organization
...> |> where([o], amount_le(o.payroll, 110))
...> |> select([o], o.payroll)
...> |> Repo.all()
[Money.new(:EUR, "100"), Money.new(:USD, "110")]
```

# `currency_eq`
*macro* 

`Ecto.Query.API` helper, allowing to filter records having the same currency.

_Example:_

```elixir
iex> Organization
...> |> where([o], currency_eq(o.payroll, :AUD))
...> |> select([o], o.payroll)
...> |> Repo.all()
[Money.new(:AUD, "50"), Money.new(:AUD, "70")
```

# `currency_in`
*macro* 

`Ecto.Query.API` helper, allowing to filter records having one
of currencies given as an argument.

_Example:_

```elixir
iex> Organization
...> |> where([o], currency_in(o.payroll, [:USD, :EUR]))
...> |> select([o], o.payroll)
...> |> Repo.all()
[Money.new(:EUR, "100"), Money.new(:USD, "100")]
```

# `money_eq`
*macro* 

`Ecto.Query.API` helper, allowing to filter records having the same amount and currency.

_Example:_

```elixir
iex> Organization
...> |> where([o], money_eq(o.payroll, Money.new!(100, :USD)))
...> |> select([o], o.payroll)
...> |> Repo.all()
[Money.new(:USD, "100"), Money.new(:USD, "100")]
```

# `total_by`
*macro* 

`Ecto.Query.API` helper, allowing to aggregate by currency, summing amount.
For more sophisticated aggregation, resort to raw `fragment`.

_Example:_

```elixir
iex> Organization
...> |> where([o], o.name == ^"Lemon Inc.")
...> |> total_by([o], o.payroll)
...> |> Repo.all()
[Money.new(:EUR, "100"), Money.new(:USD, "210")]
```

# `total_by`
*macro* 

`Ecto.Query.API` helper, allowing to aggregate by currency, suming amount.
Same as `total_by/3`, but for the single currency only.

_Example:_

```elixir
iex> Organization
...> |> where([o], o.name == ^"Lemon Inc.")
...> |> total_by([o], o.payroll, :USD)
...> |> Repo.one()
[Money.new(:USD, "210")]
```

---

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