CSV export: apply cycle_status_filter and boolean_filters when exporting all
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Moritz 2026-03-04 20:12:45 +01:00
parent 9f169b9835
commit ad641ed49e
Signed by: moritz
GPG key ID: 1020A035E5DD0824
3 changed files with 110 additions and 4 deletions

View file

@ -13,6 +13,7 @@ defmodule MvWeb.MemberExportController do
alias Mv.Authorization.Actor
alias Mv.Membership.CustomField
alias Mv.Membership.Member
alias Mv.Membership.MemberExport
alias Mv.Membership.MembersCSV
alias MvWeb.MemberLive.Index.MembershipFeeStatus
alias MvWeb.Translations.MemberFields
@ -76,10 +77,34 @@ defmodule MvWeb.MemberExportController do
query: extract_string(params, "query"),
sort_field: extract_string(params, "sort_field"),
sort_order: extract_sort_order(params),
show_current_cycle: extract_boolean(params, "show_current_cycle")
show_current_cycle: extract_boolean(params, "show_current_cycle"),
cycle_status_filter: extract_cycle_status_filter(params),
boolean_filters: extract_boolean_filters(params)
}
end
defp extract_cycle_status_filter(params) do
case Map.get(params, "cycle_status_filter") do
"paid" -> :paid
"unpaid" -> :unpaid
_ -> nil
end
end
defp extract_boolean_filters(params) do
case Map.get(params, "boolean_filters") do
map when is_map(map) ->
map
|> Enum.filter(fn {k, v} ->
is_binary(k) and is_boolean(v) and match?({:ok, _}, Ecto.UUID.cast(k))
end)
|> Enum.into(%{})
_ ->
%{}
end
end
defp split_member_fields(member_fields) do
domain_fields = Mv.Constants.member_fields() |> Enum.map(&Atom.to_string/1)
selectable = Enum.filter(member_fields, fn f -> f in domain_fields end)
@ -156,7 +181,10 @@ defmodule MvWeb.MemberExportController do
parsed
|> ensure_sort_custom_field_loaded()
with {:ok, custom_fields_by_id} <- load_custom_fields_by_id(parsed.custom_field_ids, actor),
custom_field_ids_union =
(parsed.custom_field_ids ++ Map.keys(parsed.boolean_filters || %{})) |> Enum.uniq()
with {:ok, custom_fields_by_id} <- load_custom_fields_by_id(custom_field_ids_union, actor),
{:ok, members} <- load_members_for_export(actor, parsed, custom_fields_by_id) do
columns = build_columns(conn, parsed, custom_fields_by_id)
csv_iodata = MembersCSV.export(members, columns)
@ -232,8 +260,12 @@ defmodule MvWeb.MemberExportController do
defp load_members_for_export(actor, parsed, custom_fields_by_id) do
select_fields = [:id] ++ Enum.map(parsed.selectable_member_fields, &String.to_existing_atom/1)
custom_field_ids_union =
(parsed.custom_field_ids ++ Map.keys(parsed.boolean_filters || %{})) |> Enum.uniq()
need_cycles =
parsed.computed_fields != [] and "membership_fee_status" in parsed.computed_fields
(parsed.computed_fields != [] and "membership_fee_status" in parsed.computed_fields) or
parsed.cycle_status_filter != nil
need_groups = "groups" in parsed.member_fields
@ -245,7 +277,7 @@ defmodule MvWeb.MemberExportController do
Member
|> Ash.Query.new()
|> Ash.Query.select(select_fields)
|> load_custom_field_values_query(parsed.custom_field_ids)
|> load_custom_field_values_query(custom_field_ids_union)
|> maybe_load_cycles(need_cycles, parsed.show_current_cycle)
|> maybe_load_groups(need_groups)
|> maybe_load_membership_fee_type(need_membership_fee_type)
@ -276,6 +308,10 @@ defmodule MvWeb.MemberExportController do
members
end
# When exporting "all" (no selected_ids), apply same filters as PDF: cycle status and boolean custom fields
members =
MemberExport.apply_export_filters(members, parsed, custom_fields_by_id)
# Calculate membership_fee_status for computed fields
members = add_computed_fields(members, parsed.computed_fields, parsed.show_current_cycle)