Remove future date validation for join_date
Allow join_date to be set in the future. Only validation remaining is that exit_date must be after join_date.
This commit is contained in:
parent
8f8c3f258a
commit
9a1f0fbfa6
2 changed files with 59 additions and 10 deletions
|
|
@ -242,6 +242,63 @@ defmodule Mv.Membership.Member do
|
|||
{:ok, member}
|
||||
end
|
||||
end)
|
||||
|
||||
# Trigger cycle regeneration when join_date or exit_date changes
|
||||
# Regenerates cycles based on new dates
|
||||
# Note: Cycle generation runs synchronously in test environment, asynchronously in production
|
||||
# CycleGenerator uses advisory locks and transactions internally to prevent race conditions
|
||||
change after_action(fn changeset, member, _context ->
|
||||
join_date_changed = Ash.Changeset.changing_attribute?(changeset, :join_date)
|
||||
exit_date_changed = Ash.Changeset.changing_attribute?(changeset, :exit_date)
|
||||
|
||||
if (join_date_changed || exit_date_changed) && member.membership_fee_type_id do
|
||||
if Application.get_env(:mv, :sql_sandbox, false) do
|
||||
# Run synchronously in test environment for DB sandbox compatibility
|
||||
# Use skip_lock?: true to avoid nested transactions (after_action runs within action transaction)
|
||||
# Return notifications to Ash so they are sent after commit
|
||||
case Mv.MembershipFees.CycleGenerator.generate_cycles_for_member(
|
||||
member.id,
|
||||
today: Date.utc_today(),
|
||||
skip_lock?: true
|
||||
) do
|
||||
{:ok, _cycles, notifications} ->
|
||||
{:ok, member, notifications}
|
||||
|
||||
{:error, reason} ->
|
||||
require Logger
|
||||
|
||||
Logger.warning(
|
||||
"Failed to regenerate cycles for member #{member.id}: #{inspect(reason)}"
|
||||
)
|
||||
|
||||
{:ok, member}
|
||||
end
|
||||
else
|
||||
# Run asynchronously in other environments
|
||||
# Send notifications explicitly since they cannot be returned via after_action
|
||||
Task.start(fn ->
|
||||
case Mv.MembershipFees.CycleGenerator.generate_cycles_for_member(member.id) do
|
||||
{:ok, _cycles, notifications} ->
|
||||
# Send notifications manually for async case
|
||||
if Enum.any?(notifications) do
|
||||
Ash.Notifier.notify(notifications)
|
||||
end
|
||||
|
||||
{:error, reason} ->
|
||||
require Logger
|
||||
|
||||
Logger.warning(
|
||||
"Failed to regenerate cycles for member #{member.id}: #{inspect(reason)}"
|
||||
)
|
||||
end
|
||||
end)
|
||||
|
||||
{:ok, member}
|
||||
end
|
||||
else
|
||||
{:ok, member}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
# Action to handle fuzzy search on specific fields
|
||||
|
|
@ -395,11 +452,6 @@ defmodule Mv.Membership.Member do
|
|||
end
|
||||
end
|
||||
|
||||
# Join date not in the future
|
||||
validate compare(:join_date, less_than_or_equal_to: &Date.utc_today/0),
|
||||
where: [present(:join_date)],
|
||||
message: "cannot be in the future"
|
||||
|
||||
# Exit date not before join date
|
||||
validate compare(:exit_date, greater_than: :join_date),
|
||||
where: [present([:join_date, :exit_date])],
|
||||
|
|
|
|||
|
|
@ -58,12 +58,9 @@ defmodule Mv.Membership.MemberTest do
|
|||
assert {:ok, _member} = Membership.create_member(attrs2)
|
||||
end
|
||||
|
||||
test "Join date is optional but must not be in the future" do
|
||||
test "Join date can be in the future" do
|
||||
attrs = Map.put(@valid_attrs, :join_date, Date.utc_today() |> Date.add(1))
|
||||
assert {:error, %Ash.Error.Invalid{errors: errors}} = Membership.create_member(attrs)
|
||||
assert error_message(errors, :join_date) =~ "cannot be in the future"
|
||||
attrs2 = Map.delete(@valid_attrs, :join_date)
|
||||
assert {:ok, _member} = Membership.create_member(attrs2)
|
||||
assert {:ok, _member} = Membership.create_member(attrs)
|
||||
end
|
||||
|
||||
test "Exit date is optional but must not be before join date if both are specified" do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue