refactor: reduce complexity
This commit is contained in:
parent
67072f0c52
commit
6dc398fa5a
3 changed files with 92 additions and 78 deletions
|
|
@ -63,6 +63,7 @@ defmodule Mv.Membership.Import.MemberCSV do
|
|||
chunks: list(list({pos_integer(), map()})),
|
||||
column_map: %{atom() => non_neg_integer()},
|
||||
custom_field_map: %{String.t() => non_neg_integer()},
|
||||
custom_field_lookup: %{String.t() => %{id: String.t(), value_type: atom()}},
|
||||
warnings: list(String.t())
|
||||
}
|
||||
|
||||
|
|
@ -118,11 +119,15 @@ defmodule Mv.Membership.Import.MemberCSV do
|
|||
:ok <- validate_row_count(rows, max_rows) do
|
||||
chunks = chunk_rows(rows, maps, chunk_size)
|
||||
|
||||
# Build custom field lookup for efficient value processing
|
||||
custom_field_lookup = build_custom_field_lookup(custom_fields)
|
||||
|
||||
{:ok,
|
||||
%{
|
||||
chunks: chunks,
|
||||
column_map: maps.member,
|
||||
custom_field_map: maps.custom,
|
||||
custom_field_lookup: custom_field_lookup,
|
||||
warnings: warnings
|
||||
}}
|
||||
end
|
||||
|
|
@ -140,6 +145,15 @@ defmodule Mv.Membership.Import.MemberCSV do
|
|||
{:error, "Failed to load custom fields: #{Exception.message(e)}"}
|
||||
end
|
||||
|
||||
# Builds custom field lookup map for efficient value processing
|
||||
defp build_custom_field_lookup(custom_fields) do
|
||||
custom_fields
|
||||
|> Enum.reduce(%{}, fn cf, acc ->
|
||||
id_str = to_string(cf.id)
|
||||
Map.put(acc, id_str, %{id: cf.id, value_type: cf.value_type})
|
||||
end)
|
||||
end
|
||||
|
||||
# Builds header maps using HeaderMapper and collects warnings for unknown custom fields
|
||||
defp build_header_maps(headers, custom_fields) do
|
||||
# Convert custom fields to maps with id and name
|
||||
|
|
@ -263,11 +277,13 @@ defmodule Mv.Membership.Import.MemberCSV do
|
|||
%{String.t() => non_neg_integer()},
|
||||
keyword()
|
||||
) :: {:ok, chunk_result()} | {:error, String.t()}
|
||||
def process_chunk(chunk_rows_with_lines, _column_map, _custom_field_map, _opts \\ []) do
|
||||
def process_chunk(chunk_rows_with_lines, _column_map, _custom_field_map, opts \\ []) do
|
||||
custom_field_lookup = Keyword.get(opts, :custom_field_lookup, %{})
|
||||
|
||||
{inserted, failed, errors} =
|
||||
Enum.reduce(chunk_rows_with_lines, {0, 0, []}, fn {line_number, row_map},
|
||||
{acc_inserted, acc_failed, acc_errors} ->
|
||||
case process_row(row_map, line_number) do
|
||||
case process_row(row_map, line_number, custom_field_lookup) do
|
||||
{:ok, _member} ->
|
||||
{acc_inserted + 1, acc_failed, acc_errors}
|
||||
|
||||
|
|
@ -280,9 +296,13 @@ defmodule Mv.Membership.Import.MemberCSV do
|
|||
end
|
||||
|
||||
# Processes a single row and creates member with custom field values
|
||||
defp process_row(%{member: member_attrs, custom: custom_attrs}, line_number) do
|
||||
defp process_row(
|
||||
%{member: member_attrs, custom: custom_attrs},
|
||||
line_number,
|
||||
custom_field_lookup
|
||||
) do
|
||||
# Prepare custom field values for Ash
|
||||
custom_field_values = prepare_custom_field_values(custom_attrs)
|
||||
custom_field_values = prepare_custom_field_values(custom_attrs, custom_field_lookup)
|
||||
|
||||
# Create member with custom field values
|
||||
member_attrs_with_cf =
|
||||
|
|
@ -314,53 +334,26 @@ defmodule Mv.Membership.Import.MemberCSV do
|
|||
end
|
||||
|
||||
# Prepares custom field values from row map for Ash
|
||||
defp prepare_custom_field_values(custom_attrs) when is_map(custom_attrs) do
|
||||
defp prepare_custom_field_values(custom_attrs, custom_field_lookup) when is_map(custom_attrs) do
|
||||
custom_attrs
|
||||
|> Enum.filter(fn {_id, value} -> value != nil && value != "" end)
|
||||
|> Enum.map(fn {custom_field_id_str, value} ->
|
||||
# Load custom field to get value_type and ensure ID is correct
|
||||
case load_custom_field_by_id(custom_field_id_str) do
|
||||
{:ok, custom_field} ->
|
||||
# Use the actual custom_field.id (UUID) from the database
|
||||
%{
|
||||
"custom_field_id" => to_string(custom_field.id),
|
||||
"value" => format_custom_field_value(value, custom_field.value_type)
|
||||
}
|
||||
|
||||
{:error, _} ->
|
||||
# Skip if custom field not found
|
||||
case Map.get(custom_field_lookup, custom_field_id_str) do
|
||||
nil ->
|
||||
# Custom field not found, skip
|
||||
nil
|
||||
|
||||
%{id: custom_field_id, value_type: value_type} ->
|
||||
%{
|
||||
"custom_field_id" => to_string(custom_field_id),
|
||||
"value" => format_custom_field_value(value, value_type)
|
||||
}
|
||||
end
|
||||
end)
|
||||
|> Enum.filter(&(&1 != nil))
|
||||
end
|
||||
|
||||
defp prepare_custom_field_values(_), do: []
|
||||
|
||||
# Loads a custom field by ID (string or UUID)
|
||||
defp load_custom_field_by_id(id) when is_binary(id) do
|
||||
require Ash.Query
|
||||
|
||||
try do
|
||||
# Try to parse as UUID first
|
||||
uuid_id =
|
||||
case Ecto.UUID.cast(id) do
|
||||
{:ok, uuid} -> uuid
|
||||
:error -> id
|
||||
end
|
||||
|
||||
custom_field =
|
||||
Mv.Membership.CustomField
|
||||
|> Ash.Query.filter(id == ^uuid_id)
|
||||
|> Ash.read_one!()
|
||||
|
||||
{:ok, custom_field}
|
||||
rescue
|
||||
_ -> {:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
defp load_custom_field_by_id(_), do: {:error, :invalid_id}
|
||||
defp prepare_custom_field_values(_, _), do: []
|
||||
|
||||
# Formats a custom field value according to its type
|
||||
# Uses _union_type and _union_value format as expected by Ash
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue