37 lines
1.3 KiB
Elixir
37 lines
1.3 KiB
Elixir
defmodule Mv.Membership.JoinRequest.Changes.ApproveRequest do
|
|
@moduledoc """
|
|
Sets the join request to approved and records the reviewer.
|
|
|
|
Only transitions from :submitted status. If already approved, returns error
|
|
(idempotency guard via status validation). Promotion to Member is handled
|
|
by the domain function approve_join_request/2 after calling this action.
|
|
"""
|
|
use Ash.Resource.Change
|
|
|
|
@spec change(Ash.Changeset.t(), keyword(), Ash.Resource.Change.context()) :: Ash.Changeset.t()
|
|
def change(changeset, _opts, context) do
|
|
current_status = Ash.Changeset.get_data(changeset, :status)
|
|
|
|
if current_status == :submitted do
|
|
reviewed_by_id = actor_id(context.actor)
|
|
|
|
changeset
|
|
|> Ash.Changeset.force_change_attribute(:status, :approved)
|
|
|> Ash.Changeset.force_change_attribute(:approved_at, DateTime.utc_now())
|
|
|> Ash.Changeset.force_change_attribute(:reviewed_by_user_id, reviewed_by_id)
|
|
else
|
|
Ash.Changeset.add_error(changeset,
|
|
field: :status,
|
|
message: "can only approve a submitted join request (current status: #{current_status})"
|
|
)
|
|
end
|
|
end
|
|
|
|
defp actor_id(nil), do: nil
|
|
|
|
defp actor_id(actor) when is_map(actor) do
|
|
Map.get(actor, :id) || Map.get(actor, "id")
|
|
end
|
|
|
|
defp actor_id(_), do: nil
|
|
end
|