Membership Fee 6 - UI Components & LiveViews closes #280 #304
2 changed files with 43 additions and 9 deletions
|
|
@ -299,11 +299,15 @@ defmodule Mv.MembershipFees.CalendarCycles do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp quarterly_cycle_end(cycle_start) do
|
defp quarterly_cycle_end(cycle_start) do
|
||||||
case cycle_start.month do
|
# Ensure cycle_start is aligned to quarter boundary
|
||||||
1 -> Date.new!(cycle_start.year, 3, 31)
|
# This handles cases where cycle_start might not be at the correct quarter start (e.g., month 12)
|
||||||
4 -> Date.new!(cycle_start.year, 6, 30)
|
aligned_start = quarterly_cycle_start(cycle_start)
|
||||||
7 -> Date.new!(cycle_start.year, 9, 30)
|
|
||||||
10 -> Date.new!(cycle_start.year, 12, 31)
|
case aligned_start.month do
|
||||||
|
1 -> Date.new!(aligned_start.year, 3, 31)
|
||||||
|
4 -> Date.new!(aligned_start.year, 6, 30)
|
||||||
|
7 -> Date.new!(aligned_start.year, 9, 30)
|
||||||
|
10 -> Date.new!(aligned_start.year, 12, 31)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -313,9 +317,13 @@ defmodule Mv.MembershipFees.CalendarCycles do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp half_yearly_cycle_end(cycle_start) do
|
defp half_yearly_cycle_end(cycle_start) do
|
||||||
case cycle_start.month do
|
# Ensure cycle_start is aligned to half-year boundary
|
||||||
1 -> Date.new!(cycle_start.year, 6, 30)
|
# This handles cases where cycle_start might not be at the correct half-year start (e.g., month 10)
|
||||||
7 -> Date.new!(cycle_start.year, 12, 31)
|
aligned_start = half_yearly_cycle_start(cycle_start)
|
||||||
|
|
||||||
|
case aligned_start.month do
|
||||||
|
1 -> Date.new!(aligned_start.year, 6, 30)
|
||||||
|
7 -> Date.new!(aligned_start.year, 12, 31)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -386,18 +386,44 @@ defmodule Mv.MembershipFees.CycleGenerator do
|
||||||
{:ok, cycle} ->
|
{:ok, cycle} ->
|
||||||
{:ok, cycle, []}
|
{:ok, cycle, []}
|
||||||
|
|
||||||
|
{:error, %Ash.Error.Invalid{errors: [%Ash.Error.Changes.InvalidAttribute{private_vars: %{constraint: constraint, constraint_type: :unique}}]}} = error ->
|
||||||
|
# Cycle already exists (unique constraint violation) - skip it silently
|
||||||
|
# This makes the function idempotent and prevents errors on server restart
|
||||||
|
if constraint == "membership_fee_cycles_unique_cycle_per_member_index" do
|
||||||
|
{:skip, cycle_start}
|
||||||
|
else
|
||||||
|
{:error, {cycle_start, error}}
|
||||||
|
end
|
||||||
|
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
{:error, {cycle_start, reason}}
|
{:error, {cycle_start, reason}}
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
{successes, errors} = Enum.split_with(results, &match?({:ok, _, _}, &1))
|
{successes, skips, errors} =
|
||||||
|
Enum.reduce(results, {[], [], []}, fn
|
||||||
|
{:ok, cycle, notifications}, {successes, skips, errors} ->
|
||||||
|
{[{:ok, cycle, notifications} | successes], skips, errors}
|
||||||
|
|
||||||
|
{:skip, cycle_start}, {successes, skips, errors} ->
|
||||||
|
{successes, [cycle_start | skips], errors}
|
||||||
|
|
||||||
|
{:error, error}, {successes, skips, errors} ->
|
||||||
|
{successes, skips, [error | errors]}
|
||||||
|
end)
|
||||||
|
|
||||||
all_notifications =
|
all_notifications =
|
||||||
Enum.flat_map(successes, fn {:ok, _cycle, notifications} -> notifications end)
|
Enum.flat_map(successes, fn {:ok, _cycle, notifications} -> notifications end)
|
||||||
|
|
||||||
if Enum.empty?(errors) do
|
if Enum.empty?(errors) do
|
||||||
successful_cycles = Enum.map(successes, fn {:ok, cycle, _notifications} -> cycle end)
|
successful_cycles = Enum.map(successes, fn {:ok, cycle, _notifications} -> cycle end)
|
||||||
|
|
||||||
|
if Enum.any?(skips) do
|
||||||
|
Logger.debug(
|
||||||
|
"Skipped #{length(skips)} cycles that already exist for member #{member_id}"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
{:ok, successful_cycles, all_notifications}
|
{:ok, successful_cycles, all_notifications}
|
||||||
else
|
else
|
||||||
Logger.warning("Some cycles failed to create: #{inspect(errors)}")
|
Logger.warning("Some cycles failed to create: #{inspect(errors)}")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue