feat(import): recognize group and fee-type columns and always ignore fee-status

This commit is contained in:
Moritz 2026-06-03 02:01:09 +02:00
parent 5c5fd56749
commit 95c7bf7a15
2 changed files with 250 additions and 11 deletions

View file

@ -1,5 +1,6 @@
defmodule Mv.Membership.Import.HeaderMapperTest do
use ExUnit.Case, async: true
use ExUnitProperties
alias Mv.Membership.Import.HeaderMapper
@ -272,4 +273,167 @@ defmodule Mv.Membership.Import.HeaderMapperTest do
assert unknown == []
end
end
describe "build_maps/2 fee-status ignore list" do
test "places fee-status variants in ignored, not member or custom map" do
headers = ["email", "Bezahlstatus"]
assert {:ok, result} = HeaderMapper.build_maps(headers, [])
assert result.member[:email] == 0
assert result.custom == %{}
assert result.ignored == [1]
refute Map.has_key?(result.member, :bezahlstatus)
end
test "ignores membership_fee_status snake-case variant" do
headers = ["email", "membership_fee_status"]
assert {:ok, result} = HeaderMapper.build_maps(headers, [])
assert result.ignored == [1]
assert result.custom == %{}
end
test "ignores German Mitgliedsbeitragsstatus variant" do
headers = ["email", "Mitgliedsbeitragsstatus"]
assert {:ok, result} = HeaderMapper.build_maps(headers, [])
assert result.ignored == [1]
end
test "fee-status takes priority over a same-named custom field" do
headers = ["email", "Bezahlstatus"]
custom_fields = [%{id: "cf1", name: "Bezahlstatus"}]
assert {:ok, result} = HeaderMapper.build_maps(headers, custom_fields)
assert result.ignored == [1]
assert result.custom == %{}
end
test "result carries groups_column_index and fee_type_column_index keys" do
assert {:ok, result} = HeaderMapper.build_maps(["email"], [])
assert Map.has_key?(result, :groups_column_index)
assert Map.has_key?(result, :fee_type_column_index)
end
end
describe "build_maps/2 groups column detection" do
test "detects German Gruppen variant and excludes it from member/custom maps" do
headers = ["email", "Gruppen"]
assert {:ok, result} = HeaderMapper.build_maps(headers, [])
assert result.groups_column_index == 1
assert result.custom == %{}
assert result.unknown == []
refute Map.has_key?(result.member, :gruppen)
end
test "detects English Groups variant" do
headers = ["email", "Groups"]
assert {:ok, result} = HeaderMapper.build_maps(headers, [])
assert result.groups_column_index == 1
end
test "detects singular Gruppe and lowercase groups variants" do
assert {:ok, %{groups_column_index: 1}} = HeaderMapper.build_maps(["email", "Gruppe"], [])
assert {:ok, %{groups_column_index: 1}} = HeaderMapper.build_maps(["email", "groups"], [])
end
test "groups column takes priority over a same-named custom field" do
headers = ["email", "Gruppen"]
custom_fields = [%{id: "cf1", name: "Gruppen"}]
assert {:ok, result} = HeaderMapper.build_maps(headers, custom_fields)
assert result.groups_column_index == 1
assert result.custom == %{}
end
test "groups_column_index is nil when no groups column present" do
assert {:ok, %{groups_column_index: nil}} = HeaderMapper.build_maps(["email"], [])
end
end
describe "build_maps/2 fee-type column detection" do
test "detects German Beitragsart variant and excludes it from member/custom maps" do
headers = ["email", "Beitragsart"]
assert {:ok, result} = HeaderMapper.build_maps(headers, [])
assert result.fee_type_column_index == 1
assert result.custom == %{}
assert result.unknown == []
end
test "detects English fee type variants" do
assert {:ok, %{fee_type_column_index: 1}} =
HeaderMapper.build_maps(["email", "Fee Type"], [])
assert {:ok, %{fee_type_column_index: 1}} =
HeaderMapper.build_maps(["email", "fee type"], [])
assert {:ok, %{fee_type_column_index: 1}} =
HeaderMapper.build_maps(["email", "fee_type"], [])
assert {:ok, %{fee_type_column_index: 1}} =
HeaderMapper.build_maps(["email", "membership_fee_type"], [])
end
test "fee-type column takes priority over a same-named custom field" do
headers = ["email", "Beitragsart"]
custom_fields = [%{id: "cf1", name: "Beitragsart"}]
assert {:ok, result} = HeaderMapper.build_maps(headers, custom_fields)
assert result.fee_type_column_index == 1
assert result.custom == %{}
end
test "fee_type_column_index is nil when no fee-type column present" do
assert {:ok, %{fee_type_column_index: nil}} = HeaderMapper.build_maps(["email"], [])
end
test "detects groups and fee-type columns together" do
headers = ["email", "Gruppen", "Beitragsart"]
assert {:ok, result} = HeaderMapper.build_maps(headers, [])
assert result.groups_column_index == 1
assert result.fee_type_column_index == 2
assert result.member[:email] == 0
assert result.custom == %{}
assert result.unknown == []
end
end
describe "build_maps/2 fee-status ignore property" do
property "every fee-status variant is ignored, never member or custom" do
check all(
variant <-
StreamData.member_of([
"Membership Fee Status",
"membership_fee_status",
"Mitgliedsbeitragsstatus",
"Bezahlstatus",
" Bezahlstatus ",
"BEZAHLSTATUS"
])
) do
custom_fields = [%{id: "cf1", name: variant}]
assert {:ok, result} = HeaderMapper.build_maps(["email", variant], custom_fields)
assert result.ignored == [1]
assert result.custom == %{}
refute Map.has_key?(result.member, :bezahlstatus)
end
end
end
end