hannes
hannes
AEAsh Elixir
Created by hannes on 2/5/2023 in #support
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
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?
12 replies