MemberLive: confirm_delete_all_cycles via Ash.destroy, reduce current_actor
- Delete each cycle with Ash.destroy(actor:) so policies apply; add do_delete_all_cycles/5. - Use positive can? check; remove duplicate current_actor(socket) in change_membership_fee_type.
This commit is contained in:
parent
e799f0271c
commit
182d34fe58
1 changed files with 71 additions and 56 deletions
|
|
@ -457,7 +457,7 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
||||||
|> assign(:cycles, [])
|
|> assign(:cycles, [])
|
||||||
|> assign(
|
|> assign(
|
||||||
:available_fee_types,
|
:available_fee_types,
|
||||||
get_available_fee_types(updated_member, current_actor(socket))
|
get_available_fee_types(updated_member, actor)
|
||||||
)
|
)
|
||||||
|> assign(:interval_warning, nil)
|
|> assign(:interval_warning, nil)
|
||||||
|> put_flash(:info, gettext("Membership fee type removed"))}
|
|> put_flash(:info, gettext("Membership fee type removed"))}
|
||||||
|
|
@ -488,13 +488,9 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
||||||
if interval_warning do
|
if interval_warning do
|
||||||
{:noreply, assign(socket, :interval_warning, interval_warning)}
|
{:noreply, assign(socket, :interval_warning, interval_warning)}
|
||||||
else
|
else
|
||||||
actor = current_actor(socket)
|
|
||||||
|
|
||||||
case update_member_fee_type(member, fee_type_id, actor) do
|
case update_member_fee_type(member, fee_type_id, actor) do
|
||||||
{:ok, updated_member} ->
|
{:ok, updated_member} ->
|
||||||
# Reload member with cycles
|
# Reload member with cycles
|
||||||
actor = current_actor(socket)
|
|
||||||
|
|
||||||
updated_member =
|
updated_member =
|
||||||
updated_member
|
updated_member
|
||||||
|> Ash.load!(
|
|> Ash.load!(
|
||||||
|
|
@ -520,7 +516,7 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
||||||
|> assign(:cycles, cycles)
|
|> assign(:cycles, cycles)
|
||||||
|> assign(
|
|> assign(
|
||||||
:available_fee_types,
|
:available_fee_types,
|
||||||
get_available_fee_types(updated_member, current_actor(socket))
|
get_available_fee_types(updated_member, actor)
|
||||||
)
|
)
|
||||||
|> assign(:interval_warning, nil)
|
|> assign(:interval_warning, nil)
|
||||||
|> put_flash(:info, gettext("Membership fee type updated. Cycles regenerated."))}
|
|> put_flash(:info, gettext("Membership fee type updated. Cycles regenerated."))}
|
||||||
|
|
@ -730,61 +726,31 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
||||||
confirmation = String.trim(String.downcase(socket.assigns.delete_all_confirmation))
|
confirmation = String.trim(String.downcase(socket.assigns.delete_all_confirmation))
|
||||||
expected = String.downcase(gettext("Yes"))
|
expected = String.downcase(gettext("Yes"))
|
||||||
|
|
||||||
if confirmation != expected do
|
if confirmation == expected do
|
||||||
|
member = socket.assigns.member
|
||||||
|
actor = current_actor(socket)
|
||||||
|
cycles = socket.assigns.cycles
|
||||||
|
|
||||||
|
reset_modal = fn s ->
|
||||||
|
s
|
||||||
|
|> assign(:deleting_all_cycles, false)
|
||||||
|
|> assign(:delete_all_confirmation, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
if can?(actor, :destroy, MembershipFeeCycle) do
|
||||||
|
do_delete_all_cycles(socket, member, actor, cycles, reset_modal)
|
||||||
|
else
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> reset_modal.()
|
||||||
|
|> put_flash(:error, format_error(%Ash.Error.Forbidden{}))}
|
||||||
|
end
|
||||||
|
else
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:deleting_all_cycles, false)
|
|> assign(:deleting_all_cycles, false)
|
||||||
|> assign(:delete_all_confirmation, "")
|
|> assign(:delete_all_confirmation, "")
|
||||||
|> put_flash(:error, gettext("Confirmation text does not match"))}
|
|> put_flash(:error, gettext("Confirmation text does not match"))}
|
||||||
else
|
|
||||||
member = socket.assigns.member
|
|
||||||
|
|
||||||
# Delete all cycles atomically using Ecto query
|
|
||||||
import Ecto.Query
|
|
||||||
|
|
||||||
deleted_count =
|
|
||||||
Mv.Repo.delete_all(
|
|
||||||
from c in Mv.MembershipFees.MembershipFeeCycle,
|
|
||||||
where: c.member_id == ^member.id
|
|
||||||
)
|
|
||||||
|
|
||||||
if deleted_count > 0 do
|
|
||||||
# Reload member to get updated cycles
|
|
||||||
actor = current_actor(socket)
|
|
||||||
|
|
||||||
updated_member =
|
|
||||||
member
|
|
||||||
|> Ash.load!(
|
|
||||||
[
|
|
||||||
:membership_fee_type,
|
|
||||||
membership_fee_cycles: [:membership_fee_type]
|
|
||||||
],
|
|
||||||
actor: actor
|
|
||||||
)
|
|
||||||
|
|
||||||
updated_cycles =
|
|
||||||
Enum.sort_by(
|
|
||||||
updated_member.membership_fee_cycles || [],
|
|
||||||
& &1.cycle_start,
|
|
||||||
{:desc, Date}
|
|
||||||
)
|
|
||||||
|
|
||||||
send(self(), {:member_updated, updated_member})
|
|
||||||
|
|
||||||
{:noreply,
|
|
||||||
socket
|
|
||||||
|> assign(:member, updated_member)
|
|
||||||
|> assign(:cycles, updated_cycles)
|
|
||||||
|> assign(:deleting_all_cycles, false)
|
|
||||||
|> assign(:delete_all_confirmation, "")
|
|
||||||
|> put_flash(:info, gettext("All cycles deleted"))}
|
|
||||||
else
|
|
||||||
{:noreply,
|
|
||||||
socket
|
|
||||||
|> assign(:deleting_all_cycles, false)
|
|
||||||
|> assign(:delete_all_confirmation, "")
|
|
||||||
|> put_flash(:info, gettext("No cycles to delete"))}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -903,6 +869,55 @@ defmodule MvWeb.MemberLive.Show.MembershipFeesComponent do
|
||||||
|
|
||||||
# Helper functions
|
# Helper functions
|
||||||
|
|
||||||
|
defp do_delete_all_cycles(socket, member, actor, cycles, reset_modal) do
|
||||||
|
result =
|
||||||
|
Enum.reduce_while(cycles, {:ok, 0}, fn cycle, {:ok, count} ->
|
||||||
|
case Ash.destroy(cycle, domain: MembershipFees, actor: actor) do
|
||||||
|
:ok -> {:cont, {:ok, count + 1}}
|
||||||
|
{:ok, _} -> {:cont, {:ok, count + 1}}
|
||||||
|
{:error, error} -> {:halt, {:error, error}}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
case result do
|
||||||
|
{:ok, deleted_count} when deleted_count > 0 ->
|
||||||
|
updated_member =
|
||||||
|
member
|
||||||
|
|> Ash.load!(
|
||||||
|
[:membership_fee_type, membership_fee_cycles: [:membership_fee_type]],
|
||||||
|
actor: actor
|
||||||
|
)
|
||||||
|
|
||||||
|
updated_cycles =
|
||||||
|
Enum.sort_by(
|
||||||
|
updated_member.membership_fee_cycles || [],
|
||||||
|
& &1.cycle_start,
|
||||||
|
{:desc, Date}
|
||||||
|
)
|
||||||
|
|
||||||
|
send(self(), {:member_updated, updated_member})
|
||||||
|
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> assign(:member, updated_member)
|
||||||
|
|> assign(:cycles, updated_cycles)
|
||||||
|
|> reset_modal.()
|
||||||
|
|> put_flash(:info, gettext("All cycles deleted"))}
|
||||||
|
|
||||||
|
{:ok, _} ->
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> reset_modal.()
|
||||||
|
|> put_flash(:info, gettext("No cycles to delete"))}
|
||||||
|
|
||||||
|
{:error, error} ->
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> reset_modal.()
|
||||||
|
|> put_flash(:error, format_error(error))}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp get_available_fee_types(member, actor) do
|
defp get_available_fee_types(member, actor) do
|
||||||
all_types =
|
all_types =
|
||||||
MembershipFeeType
|
MembershipFeeType
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue