diff --git a/lib/mv/vereinfacht/changes/sync_contact.ex b/lib/mv/vereinfacht/changes/sync_contact.ex index 4ea6cc8..99875e0 100644 --- a/lib/mv/vereinfacht/changes/sync_contact.ex +++ b/lib/mv/vereinfacht/changes/sync_contact.ex @@ -7,20 +7,57 @@ defmodule Mv.Vereinfacht.Changes.SyncContact do Runs in `after_transaction` so the member is persisted first. API failures are logged but do not block the member operation. Requires Vereinfacht to be configured (Mv.Config.vereinfacht_configured?/0). + + Only runs when relevant data changed: on create always; on update only when + first_name, last_name, email, street, house_number, postal_code, or city changed, + or when the member has no vereinfacht_contact_id yet (to avoid unnecessary API calls). """ use Ash.Resource.Change require Logger + @synced_attributes [ + :first_name, + :last_name, + :email, + :street, + :house_number, + :postal_code, + :city + ] + @impl true def change(changeset, _opts, _context) do - if Mv.Config.vereinfacht_configured?() do + if Mv.Config.vereinfacht_configured?() and sync_relevant?(changeset) do Ash.Changeset.after_transaction(changeset, &sync_after_transaction/2) else changeset end end + defp sync_relevant?(changeset) do + case changeset.action_type do + :create -> true + :update -> relevant_update?(changeset) + _ -> false + end + end + + defp relevant_update?(changeset) do + any_synced_attr_changed? = + Enum.any?(@synced_attributes, &Ash.Changeset.changing_attribute?(changeset, &1)) + + record = changeset.data + no_contact_id_yet? = record && blank_contact_id?(record.vereinfacht_contact_id) + + any_synced_attr_changed? or no_contact_id_yet? + end + + defp blank_contact_id?(nil), do: true + defp blank_contact_id?(""), do: true + defp blank_contact_id?(s) when is_binary(s), do: String.trim(s) == "" + defp blank_contact_id?(_), do: false + # Ash calls after_transaction with (changeset, result) only - 2 args. defp sync_after_transaction(_changeset, {:ok, member}) do case Mv.Vereinfacht.sync_member(member) do