# `GraphApi.OData.Filter`
[🔗](https://github.com/keenmate/microsoft_graph/blob/v1.0.0-rc.1/lib/graph_api/odata/filter.ex#L1)

Schema-aware OData filter builder.

Translates snake_case Elixir field names to camelCase API field names
using schema module field mappings, and builds valid OData `$filter` expressions.

## Simple keyword syntax

For equality conditions combined with `and`:

    OData.new()
    |> OData.filter(User, department: "Engineering", account_enabled: true)
    # => $filter=department eq 'Engineering' and accountEnabled eq true

## Builder syntax

For complex filters with different operators:

    alias GraphApi.OData.Filter

    filter =
      Filter.new(User)
      |> Filter.where(:display_name, :starts_with, "A")
      |> Filter.where(:account_enabled, :eq, true)
      |> Filter.or_where(:department, :eq, "Sales")

    OData.new() |> OData.filter(filter)

## Supported operators

- `:eq`, `:ne` — equality / inequality
- `:gt`, `:lt`, `:ge`, `:le` — comparison
- `:starts_with`, `:ends_with`, `:contains` — string functions
- `:in` — collection membership
- `:is_nil` — null check (use `true` for `eq null`, `false` for `ne null`)

# `operator`

```elixir
@type operator() ::
  :eq
  | :ne
  | :gt
  | :lt
  | :ge
  | :le
  | :starts_with
  | :ends_with
  | :contains
  | :in
  | :is_nil
```

# `t`

```elixir
@type t() :: %GraphApi.OData.Filter{
  clauses: [{:and | :or, atom(), operator(), term()}],
  schema: module()
}
```

# `from_keywords`

```elixir
@spec from_keywords(
  module(),
  keyword()
) :: String.t()
```

Builds a filter string from simple keyword conditions (all AND-ed with `eq`).

Used by `OData.filter/3`. Each key is a snake_case field name, each value
is compared with `eq`.

## Examples

    Filter.from_keywords(User, department: "Engineering", account_enabled: true)
    #=> "department eq 'Engineering' and accountEnabled eq true"

# `new`

```elixir
@spec new(module()) :: t()
```

Creates a new filter builder for the given schema module.

# `or_where`

```elixir
@spec or_where(t(), atom(), operator(), term()) :: t()
```

Adds an OR condition to the filter.

## Examples

    Filter.new(User)
    |> Filter.where(:department, :eq, "Engineering")
    |> Filter.or_where(:department, :eq, "Sales")

# `to_string`

```elixir
@spec to_string(t()) :: String.t()
```

Converts the filter builder to an OData filter string.

## Examples

    Filter.new(User)
    |> Filter.where(:display_name, :starts_with, "A")
    |> Filter.where(:account_enabled, :eq, true)
    |> Filter.to_string()
    #=> "startsWith(displayName,'A') and accountEnabled eq true"

# `where`

```elixir
@spec where(t(), atom(), operator(), term()) :: t()
```

Adds an AND condition to the filter.

## Examples

    Filter.new(User)
    |> Filter.where(:display_name, :eq, "Alice")
    |> Filter.where(:account_enabled, :eq, true)

---

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