refactoring

This commit is contained in:
carla 2026-02-02 13:07:08 +01:00
parent 86a3c4e50e
commit 12715f3d85

View file

@ -524,32 +524,12 @@ defmodule Mv.Membership.Import.MemberCSV do
{:error, %Error{csv_line_number: line_number, field: nil, message: first_error}}
{:ok, custom_field_values} ->
# Create member with custom field values
member_attrs_with_cf =
trimmed_member_attrs
|> Map.put(:custom_field_values, custom_field_values)
# Only include custom_field_values if not empty
final_attrs =
if Enum.empty?(custom_field_values) do
Map.delete(member_attrs_with_cf, :custom_field_values)
else
member_attrs_with_cf
end
case Mv.Membership.create_member(final_attrs, actor: actor) do
{:ok, member} ->
{:ok, member}
{:error, %Ash.Error.Invalid{} = error} ->
# Extract email from final_attrs for better error messages
email = Map.get(final_attrs, :email) || Map.get(trimmed_member_attrs, :email)
{:error, format_ash_error(error, line_number, email)}
{:error, error} ->
{:error,
%Error{csv_line_number: line_number, field: nil, message: inspect(error)}}
end
create_member_with_custom_fields(
trimmed_member_attrs,
custom_field_values,
line_number,
actor
)
end
end
rescue
@ -557,6 +537,40 @@ defmodule Mv.Membership.Import.MemberCSV do
{:error, %Error{csv_line_number: line_number, field: nil, message: Exception.message(e)}}
end
# Creates a member with custom field values, handling errors appropriately
defp create_member_with_custom_fields(
trimmed_member_attrs,
custom_field_values,
line_number,
actor
) do
# Create member with custom field values
member_attrs_with_cf =
trimmed_member_attrs
|> Map.put(:custom_field_values, custom_field_values)
# Only include custom_field_values if not empty
final_attrs =
if Enum.empty?(custom_field_values) do
Map.delete(member_attrs_with_cf, :custom_field_values)
else
member_attrs_with_cf
end
case Mv.Membership.create_member(final_attrs, actor: actor) do
{:ok, member} ->
{:ok, member}
{:error, %Ash.Error.Invalid{} = error} ->
# Extract email from final_attrs for better error messages
email = Map.get(final_attrs, :email) || Map.get(trimmed_member_attrs, :email)
{:error, format_ash_error(error, line_number, email)}
{:error, error} ->
{:error, %Error{csv_line_number: line_number, field: nil, message: inspect(error)}}
end
end
# Prepares custom field values from row map for Ash
# Returns {:ok, [custom_field_value_maps]} or {:error, [validation_errors]}
defp prepare_custom_field_values(custom_attrs, custom_field_lookup) when is_map(custom_attrs) do
@ -564,25 +578,13 @@ defmodule Mv.Membership.Import.MemberCSV do
custom_attrs
|> Enum.filter(fn {_id, value} -> value != nil && value != "" end)
|> Enum.reduce({[], []}, fn {custom_field_id_str, value}, {acc_values, acc_errors} ->
case Map.get(custom_field_lookup, custom_field_id_str) do
nil ->
# Custom field not found, skip
{acc_values, acc_errors}
%{id: custom_field_id, value_type: value_type, name: custom_field_name} ->
case format_custom_field_value(value, value_type, custom_field_name) do
{:ok, formatted_value} ->
value_map = %{
"custom_field_id" => to_string(custom_field_id),
"value" => formatted_value
}
{[value_map | acc_values], acc_errors}
{:error, reason} ->
{acc_values, [reason | acc_errors]}
end
end
process_single_custom_field(
custom_field_id_str,
value,
custom_field_lookup,
acc_values,
acc_errors
)
end)
if Enum.empty?(errors) do
@ -594,6 +596,35 @@ defmodule Mv.Membership.Import.MemberCSV do
defp prepare_custom_field_values(_, _), do: {:ok, []}
# Processes a single custom field value and returns updated accumulator
defp process_single_custom_field(
custom_field_id_str,
value,
custom_field_lookup,
acc_values,
acc_errors
) do
case Map.get(custom_field_lookup, custom_field_id_str) do
nil ->
# Custom field not found, skip
{acc_values, acc_errors}
%{id: custom_field_id, value_type: value_type, name: custom_field_name} ->
case format_custom_field_value(value, value_type, custom_field_name) do
{:ok, formatted_value} ->
value_map = %{
"custom_field_id" => to_string(custom_field_id),
"value" => formatted_value
}
{[value_map | acc_values], acc_errors}
{:error, reason} ->
{acc_values, [reason | acc_errors]}
end
end
end
# Formats a custom field value according to its type
# Uses _union_type and _union_value format as expected by Ash
# Returns {:ok, formatted_value} or {:error, error_message}
@ -620,31 +651,19 @@ defmodule Mv.Membership.Import.MemberCSV do
defp format_custom_field_value(value, :boolean, custom_field_name) when is_binary(value) do
trimmed = String.trim(value)
lower = String.downcase(trimmed)
bool_value =
case lower do
"true" -> true
"1" -> true
"yes" -> true
"ja" -> true
"false" -> false
"0" -> false
"no" -> false
"nein" -> false
_ -> nil
end
case parse_boolean_value(trimmed) do
{:ok, bool_value} ->
{:ok, %{"_union_type" => "boolean", "_union_value" => bool_value}}
if bool_value != nil do
{:ok, %{"_union_type" => "boolean", "_union_value" => bool_value}}
else
{:error,
format_custom_field_error_with_details(
custom_field_name,
:boolean,
trimmed,
gettext("(true/false/1/0/yes/no/ja/nein)")
)}
:error ->
{:error,
format_custom_field_error_with_details(
custom_field_name,
:boolean,
trimmed,
gettext("(true/false/1/0/yes/no/ja/nein)")
)}
end
end
@ -690,6 +709,23 @@ defmodule Mv.Membership.Import.MemberCSV do
{:ok, %{"_union_type" => "string", "_union_value" => String.trim(value)}}
end
# Parses a boolean value from a string, supporting multiple formats
defp parse_boolean_value(value) when is_binary(value) do
lower = String.downcase(value)
parse_boolean_value_lower(lower)
end
# Helper function with pattern matching for boolean values
defp parse_boolean_value_lower("true"), do: {:ok, true}
defp parse_boolean_value_lower("1"), do: {:ok, true}
defp parse_boolean_value_lower("yes"), do: {:ok, true}
defp parse_boolean_value_lower("ja"), do: {:ok, true}
defp parse_boolean_value_lower("false"), do: {:ok, false}
defp parse_boolean_value_lower("0"), do: {:ok, false}
defp parse_boolean_value_lower("no"), do: {:ok, false}
defp parse_boolean_value_lower("nein"), do: {:ok, false}
defp parse_boolean_value_lower(_), do: :error
# Generates a consistent error message for custom field validation failures
# Uses human-readable field type labels (e.g., "Number" instead of "integer")
defp format_custom_field_error(custom_field_name, value_type, value) do