refactor: reduce complexity
This commit is contained in:
parent
67072f0c52
commit
6dc398fa5a
3 changed files with 92 additions and 78 deletions
|
|
@ -97,17 +97,33 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
}
|
||||
|
||||
# Build reverse map: normalized_variant -> canonical_field
|
||||
# This is computed at runtime on first access and cached
|
||||
# Cached on first access for performance
|
||||
defp normalized_to_canonical do
|
||||
cached = Process.get({__MODULE__, :normalized_to_canonical})
|
||||
|
||||
if cached do
|
||||
cached
|
||||
else
|
||||
map = build_normalized_to_canonical_map()
|
||||
Process.put({__MODULE__, :normalized_to_canonical}, map)
|
||||
map
|
||||
end
|
||||
end
|
||||
|
||||
# Builds the normalized variant -> canonical field map
|
||||
defp build_normalized_to_canonical_map do
|
||||
@member_field_variants_raw
|
||||
|> Enum.flat_map(fn {canonical, variants} ->
|
||||
Enum.map(variants, fn variant ->
|
||||
{normalize_header(variant), canonical}
|
||||
end)
|
||||
end)
|
||||
|> Enum.flat_map(&map_variants_to_normalized/1)
|
||||
|> Map.new()
|
||||
end
|
||||
|
||||
# Maps a canonical field and its variants to normalized tuples
|
||||
defp map_variants_to_normalized({canonical, variants}) do
|
||||
Enum.map(variants, fn variant ->
|
||||
{normalize_header(variant), canonical}
|
||||
end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Normalizes a CSV header string for comparison.
|
||||
|
||||
|
|
@ -208,9 +224,10 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
|> String.replace(<<0x2212::utf8>>, "-")
|
||||
end
|
||||
|
||||
# Normalizes punctuation: parentheses, slashes become spaces
|
||||
# Normalizes punctuation: parentheses, slashes, underscores become spaces
|
||||
defp normalize_punctuation(str) do
|
||||
str
|
||||
|> String.replace("_", " ")
|
||||
|> String.replace(~r/[()\[\]{}]/, " ")
|
||||
|> String.replace(~r/[\/\\]/, " ")
|
||||
end
|
||||
|
|
@ -228,18 +245,18 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
result =
|
||||
headers
|
||||
|> Enum.with_index()
|
||||
|> Enum.reduce_while({%{}, [], %{}}, fn {header, index}, {acc_map, acc_unknown, acc_seen} ->
|
||||
|> Enum.reduce_while({%{}, []}, fn {header, index}, {acc_map, acc_unknown} ->
|
||||
normalized = normalize_header(header)
|
||||
|
||||
case process_member_header(header, index, normalized, acc_map, acc_seen) do
|
||||
case process_member_header(header, index, normalized, acc_map, %{}) do
|
||||
{:error, reason} ->
|
||||
{:halt, {:error, reason}}
|
||||
|
||||
{:ok, new_map, new_seen} ->
|
||||
{:cont, {new_map, acc_unknown, new_seen}}
|
||||
{:ok, new_map, _} ->
|
||||
{:cont, {new_map, acc_unknown}}
|
||||
|
||||
{:unknown} ->
|
||||
{:cont, {acc_map, [index | acc_unknown], acc_seen}}
|
||||
{:cont, {acc_map, [index | acc_unknown]}}
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
@ -247,7 +264,7 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
{:error, reason} ->
|
||||
{:error, reason}
|
||||
|
||||
{member_map, unknown_indices, _normalized_seen} ->
|
||||
{member_map, unknown_indices} ->
|
||||
validate_required_fields(member_map, unknown_indices)
|
||||
end
|
||||
end
|
||||
|
|
@ -258,17 +275,17 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
{:ok, acc_map, acc_seen}
|
||||
end
|
||||
|
||||
defp process_member_header(_header, index, normalized, acc_map, acc_seen) do
|
||||
if Map.has_key?(normalized_to_canonical(), normalized) do
|
||||
canonical = normalized_to_canonical()[normalized]
|
||||
defp process_member_header(_header, index, normalized, acc_map, _acc_seen) do
|
||||
case Map.get(normalized_to_canonical(), normalized) do
|
||||
nil ->
|
||||
{:unknown}
|
||||
|
||||
if Map.has_key?(acc_map, canonical) do
|
||||
{:error, "duplicate header for #{canonical} (normalized: #{normalized})"}
|
||||
else
|
||||
{:ok, Map.put(acc_map, canonical, index), Map.put(acc_seen, normalized, canonical)}
|
||||
end
|
||||
else
|
||||
{:unknown}
|
||||
canonical ->
|
||||
if Map.has_key?(acc_map, canonical) do
|
||||
{:error, "duplicate header for #{canonical} (normalized: #{normalized})"}
|
||||
else
|
||||
{:ok, Map.put(acc_map, canonical, index), %{}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -295,7 +312,7 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
|
||||
result =
|
||||
unknown_indices
|
||||
|> Enum.reduce_while({%{}, [], %{}}, fn index, {acc_map, acc_unknown, acc_seen} ->
|
||||
|> Enum.reduce_while({%{}, []}, fn index, {acc_map, acc_unknown} ->
|
||||
header = Enum.at(headers, index)
|
||||
normalized = normalize_header(header)
|
||||
|
||||
|
|
@ -305,16 +322,16 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
normalized,
|
||||
custom_field_lookup,
|
||||
acc_map,
|
||||
acc_seen
|
||||
%{}
|
||||
) do
|
||||
{:error, reason} ->
|
||||
{:halt, {:error, reason}}
|
||||
|
||||
{:ok, new_map, new_seen} ->
|
||||
{:cont, {new_map, acc_unknown, new_seen}}
|
||||
{:ok, new_map, _} ->
|
||||
{:cont, {new_map, acc_unknown}}
|
||||
|
||||
{:unknown} ->
|
||||
{:cont, {acc_map, [index | acc_unknown], acc_seen}}
|
||||
{:cont, {acc_map, [index | acc_unknown]}}
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
@ -322,7 +339,7 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
{:error, reason} ->
|
||||
{:error, reason}
|
||||
|
||||
{custom_map, remaining_unknown, _normalized_seen} ->
|
||||
{custom_map, remaining_unknown} ->
|
||||
{:ok, custom_map, Enum.reverse(remaining_unknown)}
|
||||
end
|
||||
end
|
||||
|
|
@ -350,10 +367,10 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
normalized,
|
||||
_custom_field_lookup,
|
||||
acc_map,
|
||||
acc_seen
|
||||
_acc_seen
|
||||
)
|
||||
when normalized == "" do
|
||||
{:ok, acc_map, acc_seen}
|
||||
{:ok, acc_map, %{}}
|
||||
end
|
||||
|
||||
defp process_custom_field_header(
|
||||
|
|
@ -362,7 +379,7 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
normalized,
|
||||
custom_field_lookup,
|
||||
acc_map,
|
||||
acc_seen
|
||||
_acc_seen
|
||||
) do
|
||||
if Map.has_key?(custom_field_lookup, normalized) do
|
||||
custom_field_id = custom_field_lookup[normalized]
|
||||
|
|
@ -370,8 +387,7 @@ defmodule Mv.Membership.Import.HeaderMapper do
|
|||
if Map.has_key?(acc_map, custom_field_id) do
|
||||
{:error, "duplicate custom field header (normalized: #{normalized})"}
|
||||
else
|
||||
{:ok, Map.put(acc_map, custom_field_id, index),
|
||||
Map.put(acc_seen, normalized, custom_field_id)}
|
||||
{:ok, Map.put(acc_map, custom_field_id, index), %{}}
|
||||
end
|
||||
else
|
||||
{:unknown}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue