add action changes for email sync
This commit is contained in:
parent
dbe1df73fd
commit
6a397c962d
7 changed files with 331 additions and 0 deletions
|
|
@ -0,0 +1,47 @@
|
|||
defmodule Mv.Accounts.User.Changes.OverrideMemberEmailOnLink do
|
||||
@moduledoc """
|
||||
Overrides member email with user email when linking a user to a member.
|
||||
|
||||
When a user is linked to a member (either during creation or update),
|
||||
this change ensures that the member's email is updated to match the user's email.
|
||||
|
||||
User.email is the source of truth when a link is established.
|
||||
|
||||
Uses `around_transaction` to guarantee atomicity - both the user
|
||||
creation/update and member email override happen in the SAME database transaction.
|
||||
"""
|
||||
use Ash.Resource.Change
|
||||
alias Mv.EmailSync.Helpers
|
||||
|
||||
@impl true
|
||||
def change(changeset, _opts, context) do
|
||||
# Skip if already syncing to avoid recursion
|
||||
if Map.get(context, :syncing_email, false) do
|
||||
changeset
|
||||
else
|
||||
# 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, user} <- Helpers.extract_record(result),
|
||||
linked_member <- get_linked_member(user) do
|
||||
Helpers.sync_email_to_linked_record(result, linked_member, user.email)
|
||||
else
|
||||
_ -> result
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
# Pattern match on nil member_id - no member linked
|
||||
defp get_linked_member(%{member_id: nil}), do: nil
|
||||
|
||||
# Load linked member by ID
|
||||
defp get_linked_member(%{member_id: id}) do
|
||||
case Ash.get(Mv.Membership.Member, id) do
|
||||
{:ok, member} -> member
|
||||
{:error, _} -> nil
|
||||
end
|
||||
end
|
||||
end
|
||||
55
lib/mv/accounts/user/changes/sync_email_to_member.ex
Normal file
55
lib/mv/accounts/user/changes/sync_email_to_member.ex
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
defmodule Mv.Accounts.User.Changes.SyncEmailToMember do
|
||||
@moduledoc """
|
||||
Synchronizes user email changes to the linked member.
|
||||
|
||||
When a user's email is updated and the user is linked to a member,
|
||||
this change automatically updates the member's email to match.
|
||||
|
||||
This ensures bidirectional email synchronization with User.email
|
||||
as the source of truth.
|
||||
|
||||
Uses `around_transaction` to guarantee atomicity - both the user
|
||||
and member 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, user} <- Helpers.extract_record(result),
|
||||
linked_member <- get_linked_member(user) do
|
||||
Helpers.sync_email_to_linked_record(result, linked_member, new_email)
|
||||
else
|
||||
_ -> result
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
defp get_linked_member(%{member_id: nil}), do: nil
|
||||
|
||||
defp get_linked_member(%{member_id: member_id}) do
|
||||
case Ash.get(Mv.Membership.Member, member_id) do
|
||||
{:ok, member} -> member
|
||||
{:error, _} -> nil
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue