refactor: reduce function nesting depth to fix Credo warnings

Extract nested conditionals into separate helper functions:
- check_amount_change/2 and related helpers in MembershipFeeTypeLive.Form
- check_interval_change/2 and related helpers in MemberLive.Form

This reduces nesting depth from 3 to 2, improving code readability.
This commit is contained in:
Moritz 2025-12-16 11:07:28 +01:00
parent 1fde2985e5
commit bc989422e2
Signed by: moritz
GPG key ID: 1020A035E5DD0824
2 changed files with 92 additions and 63 deletions

View file

@ -272,39 +272,7 @@ defmodule MvWeb.MemberLive.Form do
validated_form = AshPhoenix.Form.validate(socket.assigns.form, member_params) validated_form = AshPhoenix.Form.validate(socket.assigns.form, member_params)
# Check for interval mismatch if membership_fee_type_id changed # Check for interval mismatch if membership_fee_type_id changed
socket = socket = check_interval_change(socket, member_params)
if Map.has_key?(member_params, "membership_fee_type_id") &&
socket.assigns.member &&
socket.assigns.member.membership_fee_type do
new_fee_type_id = member_params["membership_fee_type_id"]
if new_fee_type_id != "" &&
new_fee_type_id != socket.assigns.member.membership_fee_type_id do
new_fee_type = find_fee_type(socket.assigns.available_fee_types, new_fee_type_id)
if new_fee_type &&
new_fee_type.interval != socket.assigns.member.membership_fee_type.interval do
assign(
socket,
:interval_warning,
gettext(
"Warning: Changing from %{old_interval} to %{new_interval} is not allowed. Please select a membership fee type with the same interval.",
old_interval:
MembershipFeeHelpers.format_interval(
socket.assigns.member.membership_fee_type.interval
),
new_interval: MembershipFeeHelpers.format_interval(new_fee_type.interval)
)
)
else
assign(socket, :interval_warning, nil)
end
else
assign(socket, :interval_warning, nil)
end
else
socket
end
{:noreply, assign(socket, form: validated_form)} {:noreply, assign(socket, form: validated_form)}
end end
@ -427,6 +395,53 @@ defmodule MvWeb.MemberLive.Form do
end end
end end
# Checks if membership fee type interval changed and updates socket assigns
defp check_interval_change(socket, member_params) do
if Map.has_key?(member_params, "membership_fee_type_id") &&
socket.assigns.member &&
socket.assigns.member.membership_fee_type do
handle_interval_change(socket, member_params["membership_fee_type_id"])
else
socket
end
end
# Handles interval change validation
defp handle_interval_change(socket, new_fee_type_id) do
if new_fee_type_id != "" &&
new_fee_type_id != socket.assigns.member.membership_fee_type_id do
validate_interval_match(socket, new_fee_type_id)
else
assign(socket, :interval_warning, nil)
end
end
# Validates that new fee type has same interval as current
defp validate_interval_match(socket, new_fee_type_id) do
new_fee_type = find_fee_type(socket.assigns.available_fee_types, new_fee_type_id)
if new_fee_type &&
new_fee_type.interval != socket.assigns.member.membership_fee_type.interval do
show_interval_warning(socket, new_fee_type)
else
assign(socket, :interval_warning, nil)
end
end
# Shows interval mismatch warning
defp show_interval_warning(socket, new_fee_type) do
assign(
socket,
:interval_warning,
gettext(
"Warning: Changing from %{old_interval} to %{new_interval} is not allowed. Please select a membership fee type with the same interval.",
old_interval:
MembershipFeeHelpers.format_interval(socket.assigns.member.membership_fee_type.interval),
new_interval: MembershipFeeHelpers.format_interval(new_fee_type.interval)
)
)
end
defp find_fee_type(fee_types, fee_type_id) do defp find_fee_type(fee_types, fee_type_id) do
Enum.find(fee_types, &(&1.id == fee_type_id)) Enum.find(fee_types, &(&1.id == fee_type_id))
end end

View file

@ -195,36 +195,7 @@ defmodule MvWeb.MembershipFeeTypeLive.Form do
validated_form = AshPhoenix.Form.validate(socket.assigns.form, params) validated_form = AshPhoenix.Form.validate(socket.assigns.form, params)
# Check if amount changed on edit # Check if amount changed on edit
socket = socket = check_amount_change(socket, params)
if socket.assigns.membership_fee_type && Map.has_key?(params, "amount") do
new_amount_str = params["amount"]
old_amount = socket.assigns.membership_fee_type.amount
case Decimal.parse(new_amount_str) do
{new_amount, _} when is_struct(new_amount, Decimal) ->
if Decimal.compare(new_amount, old_amount) != :eq do
# Amount changed - show warning
affected_count = get_affected_member_count(socket.assigns.membership_fee_type.id)
socket
|> assign(:show_amount_warning, true)
|> assign(:old_amount, old_amount)
|> assign(:new_amount, new_amount)
|> assign(:affected_member_count, affected_count)
|> assign(:pending_amount, new_amount_str)
else
# Amount unchanged - hide warning
socket
|> assign(:show_amount_warning, false)
|> assign(:pending_amount, nil)
end
:error ->
socket
end
else
socket
end
{:noreply, assign(socket, form: validated_form)} {:noreply, assign(socket, form: validated_form)}
end end
@ -322,6 +293,49 @@ defmodule MvWeb.MembershipFeeTypeLive.Form do
defp return_path("index", _membership_fee_type), do: ~p"/membership_fee_types" defp return_path("index", _membership_fee_type), do: ~p"/membership_fee_types"
@spec get_affected_member_count(String.t()) :: non_neg_integer() @spec get_affected_member_count(String.t()) :: non_neg_integer()
# Checks if amount changed and updates socket assigns accordingly
defp check_amount_change(socket, params) do
if socket.assigns.membership_fee_type && Map.has_key?(params, "amount") do
handle_amount_change(socket, params["amount"], socket.assigns.membership_fee_type.amount)
else
socket
end
end
# Handles amount change detection and warning assignment
defp handle_amount_change(socket, new_amount_str, old_amount) do
case Decimal.parse(new_amount_str) do
{new_amount, _} when is_struct(new_amount, Decimal) ->
if Decimal.compare(new_amount, old_amount) != :eq do
show_amount_warning(socket, old_amount, new_amount, new_amount_str)
else
hide_amount_warning(socket)
end
:error ->
socket
end
end
# Shows amount change warning with affected member count
defp show_amount_warning(socket, old_amount, new_amount, new_amount_str) do
affected_count = get_affected_member_count(socket.assigns.membership_fee_type.id)
socket
|> assign(:show_amount_warning, true)
|> assign(:old_amount, old_amount)
|> assign(:new_amount, new_amount)
|> assign(:affected_member_count, affected_count)
|> assign(:pending_amount, new_amount_str)
end
# Hides amount change warning
defp hide_amount_warning(socket) do
socket
|> assign(:show_amount_warning, false)
|> assign(:pending_amount, nil)
end
defp get_affected_member_count(fee_type_id) do defp get_affected_member_count(fee_type_id) do
case Ash.count(Member |> Ash.Query.filter(membership_fee_type_id == ^fee_type_id)) do case Ash.count(Member |> Ash.Query.filter(membership_fee_type_id == ^fee_type_id)) do
{:ok, count} -> count {:ok, count} -> count