ash_double_entry/lib/balance/changes/adjust_balance.ex

46 lines
1.2 KiB
Elixir
Raw Normal View History

defmodule AshDoubleEntry.Balance.Changes.AdjustBalance do
@moduledoc false
use Ash.Resource.Change
def change(changeset, _, _) do
amount_delta = changeset.arguments.delta
new_balance =
if changeset.data.account_id == changeset.arguments.from_account_id do
Money.sub!(changeset.data.balance, amount_delta)
else
Money.add!(changeset.data.balance, amount_delta)
end
Ash.Changeset.force_change_attribute(changeset, :balance, new_balance)
end
def atomic(changeset, opts, _) do
amount_delta = changeset.arguments.delta
if Ash.Expr.expr?(amount_delta) do
raise """
Amount delta is dynamic. The balance adjustment logic does not support this.
Expected a literal money value, got an expression: #{inspect(amount_delta)}
"""
end
if opts[:can_add_money?] do
{:atomic,
%{
balance:
expr(
if account_id == ^changeset.arguments.from_account_id do
^atomic_ref(:balance) + -(^amount_delta)
else
^atomic_ref(:balance) + ^amount_delta
end
)
}}
else
{:not_atomic, "Data layer cannot add money, so balance cannot be adjusted atomically"}
end
end
end