mitgliederverwaltung/lib/mv/membership/member/changes/sync_email_to_user.ex
Moritz 1c31b821ba
All checks were successful
continuous-integration/drone/push Build is passing
add action changes for email sync
2025-10-16 19:04:50 +02:00

53 lines
1.6 KiB
Elixir

defmodule Mv.Membership.Member.Changes.SyncEmailToUser do
@moduledoc """
Synchronizes member email changes to the linked user.
When a member's email is updated and the member is linked to a user,
this change automatically updates the user's email to match.
This ensures bidirectional email synchronization.
Uses `around_transaction` to guarantee atomicity - both the member
and user updates happen in the SAME database transaction.
"""
use Ash.Resource.Change
alias Mv.EmailSync.Helpers
@impl true
def change(changeset, _opts, context) do
cond do
# Skip if already syncing to avoid recursion
Map.get(context, :syncing_email, false) ->
changeset
# Only proceed if email is actually changing
not Ash.Changeset.changing_attribute?(changeset, :email) ->
changeset
# Apply the sync logic
true ->
new_email = Ash.Changeset.get_attribute(changeset, :email)
# around_transaction receives the changeset (cs) from Ash
# and a callback that executes the actual database operation
Ash.Changeset.around_transaction(changeset, fn cs, callback ->
result = callback.(cs)
with {:ok, member} <- Helpers.extract_record(result),
linked_user <- get_linked_user(member) do
Helpers.sync_email_to_linked_record(result, linked_user, new_email)
else
_ -> result
end
end)
end
end
# Load the linked user relationship (returns nil if not linked)
defp get_linked_user(member) do
case Ash.load(member, :user) do
{:ok, %{user: user}} -> user
{:error, _} -> nil
end
end
end