feat: add membership fee status to columns and dropdown
This commit is contained in:
parent
36e57b24be
commit
e1266944b1
7 changed files with 725 additions and 514 deletions
|
|
@ -14,8 +14,12 @@ defmodule MvWeb.MemberExportController do
|
|||
alias Mv.Membership.CustomField
|
||||
alias Mv.Membership.Member
|
||||
alias Mv.Membership.MembersCSV
|
||||
alias MvWeb.Translations.MemberFields
|
||||
alias MvWeb.MemberLive.Index.MembershipFeeStatus
|
||||
use Gettext, backend: MvWeb.Gettext
|
||||
|
||||
@member_fields_allowlist Mv.Constants.member_fields() |> Enum.map(&Atom.to_string/1)
|
||||
@computed_export_fields ["membership_fee_status"]
|
||||
@custom_field_prefix Mv.Constants.custom_field_prefix()
|
||||
|
||||
def export(conn, params) do
|
||||
|
|
@ -58,17 +62,38 @@ defmodule MvWeb.MemberExportController do
|
|||
end
|
||||
|
||||
defp parse_and_validate(params) do
|
||||
member_fields = filter_allowed_member_fields(extract_list(params, "member_fields"))
|
||||
{selectable_member_fields, computed_fields} = split_member_fields(member_fields)
|
||||
|
||||
%{
|
||||
selected_ids: filter_valid_uuids(extract_list(params, "selected_ids")),
|
||||
member_fields: filter_allowed_member_fields(extract_list(params, "member_fields")),
|
||||
computed_fields: filter_existing_atoms(extract_list(params, "computed_fields")),
|
||||
member_fields: member_fields,
|
||||
selectable_member_fields: selectable_member_fields,
|
||||
computed_fields:
|
||||
computed_fields ++ filter_existing_atoms(extract_list(params, "computed_fields")),
|
||||
custom_field_ids: filter_valid_uuids(extract_list(params, "custom_field_ids")),
|
||||
query: extract_string(params, "query"),
|
||||
sort_field: extract_string(params, "sort_field"),
|
||||
sort_order: extract_sort_order(params)
|
||||
sort_order: extract_sort_order(params),
|
||||
show_current_cycle: extract_boolean(params, "show_current_cycle")
|
||||
}
|
||||
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)
|
||||
computed = Enum.filter(member_fields, fn f -> f in @computed_export_fields end)
|
||||
{selectable, computed}
|
||||
end
|
||||
|
||||
defp extract_boolean(params, key) do
|
||||
case Map.get(params, key) do
|
||||
true -> true
|
||||
"true" -> true
|
||||
_ -> false
|
||||
end
|
||||
end
|
||||
|
||||
defp filter_existing_atoms(list) when is_list(list) do
|
||||
list
|
||||
|> Enum.filter(&is_binary/1)
|
||||
|
|
@ -198,13 +223,17 @@ defmodule MvWeb.MemberExportController do
|
|||
end
|
||||
|
||||
defp load_members_for_export(actor, parsed, custom_fields_by_id) do
|
||||
select_fields = [:id] ++ Enum.map(parsed.member_fields, &String.to_existing_atom/1)
|
||||
select_fields = [:id] ++ Enum.map(parsed.selectable_member_fields, &String.to_existing_atom/1)
|
||||
|
||||
need_cycles =
|
||||
parsed.computed_fields != [] and "membership_fee_status" in parsed.computed_fields
|
||||
|
||||
query =
|
||||
Member
|
||||
|> Ash.Query.new()
|
||||
|> Ash.Query.select(select_fields)
|
||||
|> load_custom_field_values_query(parsed.custom_field_ids)
|
||||
|> maybe_load_cycles(need_cycles, parsed.show_current_cycle)
|
||||
|
||||
query =
|
||||
if parsed.selected_ids != [] do
|
||||
|
|
@ -232,6 +261,9 @@ defmodule MvWeb.MemberExportController do
|
|||
members
|
||||
end
|
||||
|
||||
# Calculate membership_fee_status for computed fields
|
||||
members = add_computed_fields(members, parsed.computed_fields, parsed.show_current_cycle)
|
||||
|
||||
{:ok, members}
|
||||
|
||||
{:error, %Ash.Error.Forbidden{}} ->
|
||||
|
|
@ -239,6 +271,31 @@ defmodule MvWeb.MemberExportController do
|
|||
end
|
||||
end
|
||||
|
||||
defp maybe_load_cycles(query, false, _show_current), do: query
|
||||
|
||||
defp maybe_load_cycles(query, true, show_current) do
|
||||
MembershipFeeStatus.load_cycles_for_members(query, show_current)
|
||||
end
|
||||
|
||||
# Adds computed field values to members (e.g. membership_fee_status)
|
||||
defp add_computed_fields(members, computed_fields, show_current_cycle) do
|
||||
if "membership_fee_status" in computed_fields do
|
||||
Enum.map(members, fn member ->
|
||||
status = MembershipFeeStatus.get_cycle_status_for_member(member, show_current_cycle)
|
||||
status_string = format_membership_fee_status(status)
|
||||
Map.put(member, :membership_fee_status, status_string)
|
||||
end)
|
||||
else
|
||||
members
|
||||
end
|
||||
end
|
||||
|
||||
# Formats membership fee status as German string
|
||||
defp format_membership_fee_status(:paid), do: gettext("paid")
|
||||
defp format_membership_fee_status(:unpaid), do: gettext("unpaid")
|
||||
defp format_membership_fee_status(:suspended), do: gettext("suspended")
|
||||
defp format_membership_fee_status(nil), do: ""
|
||||
|
||||
defp load_custom_field_values_query(query, []), do: query
|
||||
|
||||
defp load_custom_field_values_query(query, custom_field_ids) do
|
||||
|
|
@ -360,7 +417,7 @@ defmodule MvWeb.MemberExportController do
|
|||
|
||||
defp build_columns(conn, parsed, custom_fields_by_id) do
|
||||
member_cols =
|
||||
Enum.map(parsed.member_fields, fn field ->
|
||||
Enum.map(parsed.selectable_member_fields, fn field ->
|
||||
%{
|
||||
header: member_field_header(conn, field),
|
||||
kind: :member_field,
|
||||
|
|
@ -373,7 +430,7 @@ defmodule MvWeb.MemberExportController do
|
|||
%{
|
||||
header: computed_field_header(conn, key),
|
||||
kind: :computed,
|
||||
key: key
|
||||
key: String.to_existing_atom(key)
|
||||
}
|
||||
end)
|
||||
|
||||
|
|
@ -398,15 +455,36 @@ defmodule MvWeb.MemberExportController do
|
|||
member_cols ++ computed_cols ++ custom_cols
|
||||
end
|
||||
|
||||
# --- headers: hier solltest du idealerweise eure bestehenden "display name" Helfer verwenden ---
|
||||
# --- headers: use MemberFields.label for translations ---
|
||||
defp member_field_header(_conn, field) when is_binary(field) do
|
||||
# TODO: hier euren bestehenden display-name helper verwenden (wie Tabelle)
|
||||
humanize_field(field)
|
||||
field
|
||||
|> String.to_existing_atom()
|
||||
|> MemberFields.label()
|
||||
rescue
|
||||
ArgumentError ->
|
||||
# Fallback for unknown fields
|
||||
humanize_field(field)
|
||||
end
|
||||
|
||||
defp computed_field_header(_conn, key) when is_atom(key) do
|
||||
# Map export-only alias to canonical UI key for translation
|
||||
atom_key = if key == :payment_status, do: :membership_fee_status, else: key
|
||||
MemberFields.label(atom_key)
|
||||
end
|
||||
|
||||
defp computed_field_header(_conn, key) when is_binary(key) do
|
||||
# TODO: display-name helper für computed fields verwenden
|
||||
humanize_field(key)
|
||||
# Map export-only alias to canonical UI key for translation
|
||||
atom_key =
|
||||
case key do
|
||||
"payment_status" -> :membership_fee_status
|
||||
_ -> String.to_existing_atom(key)
|
||||
end
|
||||
|
||||
MemberFields.label(atom_key)
|
||||
rescue
|
||||
ArgumentError ->
|
||||
# Fallback for unknown computed fields
|
||||
humanize_field(key)
|
||||
end
|
||||
|
||||
defp custom_field_header(_conn, cf) do
|
||||
|
|
@ -417,7 +495,8 @@ defmodule MvWeb.MemberExportController do
|
|||
defp humanize_field(str) do
|
||||
str
|
||||
|> String.replace("_", " ")
|
||||
|> String.capitalize()
|
||||
|> String.split()
|
||||
|> Enum.map_join(" ", &String.capitalize/1)
|
||||
end
|
||||
|
||||
defp extract_sort_value(%Ash.Union{value: value, type: type}, _),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue