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 alias Mv.Membership.JoinRequest.Changes.Helpers @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 = Helpers.actor_id(context.actor) reviewed_by_display = Helpers.actor_email(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) |> Ash.Changeset.force_change_attribute(:reviewed_by_display, reviewed_by_display) else Ash.Changeset.add_error(changeset, field: :status, message: "can only approve a submitted join request (current status: #{current_status})" ) end end end