Ash FrameworkAF
Ash Framework3y ago
11 replies
hannes

Calculations and AshPhoenix.Form

First post! So thanks @Zach Daniel for this awesome library. Looks really promising!

I'm working on a side project where I have to store employee contracts. For each contract I store the employment (as factor between 0 and 1) and the number of vacation days per year (when working full time).

defmodule MyApp.Users.Contract do
  attributes do
    # other attributes
    attribute :emp_factor, :decimal, allow_nil?: false, default: Decimal.new(1)
    attribute :vac_days, :decimal, allow_nil?: false, default: Decimal.new(25)
  end

  create :create do
    primary? true
    argument :user_id, :integer, allow_nil?: false
    argument :emp_percent, :decimal, allow_nil?: false, default: Decimal.new(100)
  end

  changes do
    change manage_relationship(:user_id, :user, type: :replace), on: :create
    change &change_emp_factor/2
  end

  calculations do
    calculate :vac_days_eff,
              :decimal,
              expr(vac_days * emp_factor)
  
    calculate :emp_percent,
              :decimal,
              expr(emp_factor * 100)
  end

  defp change_emp_factor(changeset, _) do
    case Ash.Changeset.get_argument(changeset, :emp_percent) do
      nil ->
        changeset

      emp_percent ->
        emp_factor = Decimal.div(emp_percent, 100)
        Ash.Changeset.change_attribute(changeset, :emp_factor, emp_factor)
    end
  end

  # relationships etc
end


I'm using AshPhoenix.Form.for_action() and LiveView to create a form (see screenshot) where the user can enter the employment as percentage (argument emp_percent) and the number of vacation days (attribute vac_days) and the hint should show the calculated effective vacation days based on the employment factor.

I'm already validating the form on change but I would like vac_days_eff to be recalculated each time (so I can show it in the hint below the field). I might also be a bit confused about action attributes/arguments. Could this be solved using a private action argument?
Was this page helpful?