How use filter with ash.calculation?

defmodule Project.Calculations.ActiveCustomer do
  use Ash.Calculation

  alias Project.Customer
  
  @impl true
  def calculate(records, _opts, %{}) do
    Enum.map(records, fn record ->
      active_customer?(record)
    end)
  end

  defp active_customer?(%Client{amount: amount, status: status})
       when amount > 0 and status == :active,
       do: true

  defp active_customer?(_), do: false
end
efmodule Project.Customer do
  use Ash.Resource, data_layer: AshPostgres.DataLayer

  alias Project.Calculations.ActiveCustomer

  postgres do
    table("customer")

    repo(Project.Repo)
  end

  attributes do
    uuid_primary_key :id
    create_timestamp :inserted_at
    update_timestamp :updated_at
    attribute :name, :string, do: allow_nil? false
    attribute :identificacao_cliente, :string, do: allow_nil? false 
    attribute :status, :boolean, do: allow_nil? false

    attribute :amount, :integer do
      allow_nil? false
      default 0
    end
  end


  code_interface do
    define_for(Project.Operaction)
    define :by_id_and_active_customer, args: [:id], action: :by_id_and_active_customer
  end

  actions do
    defaults([:read])

    read :by_id_and_active_customer do
      prepare(build(load: :active_customer?))
      argument(:id, :uuid, allow_nil?: false)
      get?(true)
      filter(expr(id == ^arg(:id) and active_customer? == true))
    end
  end

  calculations do
    calculate :active_customer?, :boolean, ActiveCustomer
  end
end

when execute Project.Customer.by_id_and_active_customer “48804d19-4747-45ae-96c3-9738cf724f4d”, than show an error:

(exit) an exception was raised:
    ** (UndefinedFunctionError) function Project.Calculations.ActiveCustomer.expression/2 is undefined or private

I readed the manual, but it haven’t example for use with expression.

https://hexdocs.pm/ash/Ash.Calculation.html

I need to use calculation, because, i have more code. I simplified the code.

Can someone help me?

You cannot filter on a calculation that is defined in elixir using calculate/3.

calculate :active_customer?, :boolean, expr(amount > 0 and status == :active)

If you define your calculation with an expression, you will be able to use it in filters.

I need to use calculation, because, i have more code. I simplified the code.

I need to use calculation, because, i have more code. I simplified the code.

I cannot filter, correct? I refactor my code. Tks!

Correct, you cannot use that in a filter. You can do a lot using expressions, so consider if that is possible. Keep in mind that you can use fragment to embed raw sql into an expression, i.e expr(fragment("SOME ? SQL ? WITH ? SAFE ? INTERPOLATION", field1, field2))

1 Like