2023-04-22 16:33:28 +12:00
|
|
|
defmodule AshStateMachine.BuiltinChanges.TransitionState do
|
2023-09-16 01:40:28 +12:00
|
|
|
@moduledoc false
|
2023-04-22 07:25:39 +12:00
|
|
|
use Ash.Resource.Change
|
|
|
|
|
|
|
|
def change(changeset, opts, _) do
|
2023-04-22 16:33:28 +12:00
|
|
|
AshStateMachine.transition_state(changeset, opts[:target])
|
2023-04-22 07:25:39 +12:00
|
|
|
end
|
2024-04-17 12:58:33 +12:00
|
|
|
|
|
|
|
def atomic(changeset, opts, _) do
|
|
|
|
transitions =
|
|
|
|
AshStateMachine.Info.state_machine_transitions(changeset.resource, changeset.action.name)
|
|
|
|
|
|
|
|
attribute = AshStateMachine.Info.state_machine_state_attribute!(changeset.resource)
|
2024-07-14 08:13:54 +12:00
|
|
|
|
2024-04-17 12:58:33 +12:00
|
|
|
old_state = expr(^ref(attribute))
|
|
|
|
target = opts[:target]
|
|
|
|
all_states = AshStateMachine.Info.state_machine_all_states(changeset.resource)
|
|
|
|
|
2024-04-17 13:32:42 +12:00
|
|
|
if !Ash.Expr.expr?(target) && target not in all_states do
|
|
|
|
{:atomic, AshStateMachine.no_such_state(changeset, target), %{}}
|
|
|
|
else
|
|
|
|
states_expr =
|
|
|
|
Enum.reduce(transitions, nil, fn transition, expr ->
|
|
|
|
state_expr =
|
|
|
|
expr(
|
|
|
|
^old_state in ^List.wrap(transition.from) and ^target in ^List.wrap(transition.to)
|
2024-04-17 12:58:33 +12:00
|
|
|
)
|
|
|
|
|
2024-07-14 08:13:54 +12:00
|
|
|
if is_nil(expr) do
|
|
|
|
state_expr
|
|
|
|
else
|
|
|
|
expr(^state_expr or ^expr)
|
2024-04-17 13:32:42 +12:00
|
|
|
end
|
2024-07-14 08:13:54 +12:00
|
|
|
end)
|
2024-04-17 13:32:42 +12:00
|
|
|
|
2024-07-14 08:13:54 +12:00
|
|
|
has_matching_transition =
|
|
|
|
{:atomic, [], expr(not (^states_expr)),
|
|
|
|
expr(
|
|
|
|
error(
|
|
|
|
AshStateMachine.Errors.NoMatchingTransition,
|
|
|
|
%{
|
|
|
|
old_state: ^old_state,
|
|
|
|
target: ^target,
|
|
|
|
action: ^changeset.action.name
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)}
|
|
|
|
|
|
|
|
{:atomic, changeset, %{attribute => opts[:target]},
|
|
|
|
[
|
|
|
|
has_matching_transition
|
|
|
|
]}
|
2024-04-17 13:32:42 +12:00
|
|
|
end
|
2024-04-17 12:58:33 +12:00
|
|
|
end
|
2023-04-22 07:25:39 +12:00
|
|
|
end
|