Member/Setting/validations: domain, actor, and seeds
- setting.ex: domain/authorize for default_membership_fee_type_id check - validate_same_interval: require membership_fee_type (no None) - set_membership_fee_start_date: domain/actor for fee type lookup - Validations: domain/authorize for cross-resource checks - helpers.ex, email_sync change, seeds.exs actor/authorize fixes - Update related tests
This commit is contained in:
parent
5889683854
commit
5ed41555e9
13 changed files with 118 additions and 55 deletions
|
|
@ -155,12 +155,23 @@ defmodule Mv.Membership.Setting do
|
||||||
on: [:create, :update]
|
on: [:create, :update]
|
||||||
|
|
||||||
# Validate default_membership_fee_type_id exists if set
|
# Validate default_membership_fee_type_id exists if set
|
||||||
validate fn changeset, _context ->
|
validate fn changeset, context ->
|
||||||
fee_type_id =
|
fee_type_id =
|
||||||
Ash.Changeset.get_attribute(changeset, :default_membership_fee_type_id)
|
Ash.Changeset.get_attribute(changeset, :default_membership_fee_type_id)
|
||||||
|
|
||||||
if fee_type_id do
|
if fee_type_id do
|
||||||
case Ash.get(Mv.MembershipFees.MembershipFeeType, fee_type_id) do
|
# Actor may be in changeset.context (action context) or validation context
|
||||||
|
ctx = changeset.context || %{}
|
||||||
|
|
||||||
|
actor =
|
||||||
|
get_in(ctx, [:private, :actor]) ||
|
||||||
|
Map.get(ctx, :actor) ||
|
||||||
|
(context && Map.get(context, :actor))
|
||||||
|
|
||||||
|
# Check existence only; action is already restricted by policy (e.g. admin).
|
||||||
|
opts = [domain: Mv.MembershipFees, authorize?: false]
|
||||||
|
|
||||||
|
case Ash.get(Mv.MembershipFees.MembershipFeeType, fee_type_id, opts) do
|
||||||
{:ok, _} ->
|
{:ok, _} ->
|
||||||
:ok
|
:ok
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,12 @@ defmodule Mv.MembershipFees.Changes.SetMembershipFeeStartDate do
|
||||||
alias Mv.MembershipFees.CalendarCycles
|
alias Mv.MembershipFees.CalendarCycles
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def change(changeset, _opts, _context) do
|
def change(changeset, _opts, context) do
|
||||||
# Only calculate if membership_fee_start_date is not already set
|
# Only calculate if membership_fee_start_date is not already set
|
||||||
if has_start_date?(changeset) do
|
if has_start_date?(changeset) do
|
||||||
changeset
|
changeset
|
||||||
else
|
else
|
||||||
calculate_and_set_start_date(changeset)
|
calculate_and_set_start_date(changeset, context)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -56,10 +56,13 @@ defmodule Mv.MembershipFees.Changes.SetMembershipFeeStartDate do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp calculate_and_set_start_date(changeset) do
|
defp calculate_and_set_start_date(changeset, context) do
|
||||||
|
actor = Map.get(context || %{}, :actor)
|
||||||
|
opts = if actor, do: [actor: actor], else: []
|
||||||
|
|
||||||
with {:ok, join_date} <- get_join_date(changeset),
|
with {:ok, join_date} <- get_join_date(changeset),
|
||||||
{:ok, membership_fee_type_id} <- get_membership_fee_type_id(changeset),
|
{:ok, membership_fee_type_id} <- get_membership_fee_type_id(changeset),
|
||||||
{:ok, interval} <- get_interval(membership_fee_type_id),
|
{:ok, interval} <- get_interval(membership_fee_type_id, opts),
|
||||||
{:ok, include_joining_cycle} <- get_include_joining_cycle() do
|
{:ok, include_joining_cycle} <- get_include_joining_cycle() do
|
||||||
start_date = calculate_start_date(join_date, interval, include_joining_cycle)
|
start_date = calculate_start_date(join_date, interval, include_joining_cycle)
|
||||||
Ash.Changeset.force_change_attribute(changeset, :membership_fee_start_date, start_date)
|
Ash.Changeset.force_change_attribute(changeset, :membership_fee_start_date, start_date)
|
||||||
|
|
@ -118,8 +121,8 @@ defmodule Mv.MembershipFees.Changes.SetMembershipFeeStartDate do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_interval(membership_fee_type_id) do
|
defp get_interval(membership_fee_type_id, opts) do
|
||||||
case Ash.get(Mv.MembershipFees.MembershipFeeType, membership_fee_type_id) do
|
case Ash.get(Mv.MembershipFees.MembershipFeeType, membership_fee_type_id, opts) do
|
||||||
{:ok, %{interval: interval}} -> {:ok, interval}
|
{:ok, %{interval: interval}} -> {:ok, interval}
|
||||||
{:error, _} -> {:error, :membership_fee_type_not_found}
|
{:error, _} -> {:error, :membership_fee_type_not_found}
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ defmodule Mv.MembershipFees.Changes.ValidateSameInterval do
|
||||||
use Ash.Resource.Change
|
use Ash.Resource.Change
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def change(changeset, _opts, _context) do
|
def change(changeset, _opts, context) do
|
||||||
if changing_membership_fee_type?(changeset) do
|
if changing_membership_fee_type?(changeset) do
|
||||||
validate_interval_match(changeset)
|
validate_interval_match(changeset, context)
|
||||||
else
|
else
|
||||||
changeset
|
changeset
|
||||||
end
|
end
|
||||||
|
|
@ -33,9 +33,10 @@ defmodule Mv.MembershipFees.Changes.ValidateSameInterval do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Validate that the new type has the same interval as the current type
|
# Validate that the new type has the same interval as the current type
|
||||||
defp validate_interval_match(changeset) do
|
defp validate_interval_match(changeset, context) do
|
||||||
current_type_id = get_current_type_id(changeset)
|
current_type_id = get_current_type_id(changeset)
|
||||||
new_type_id = get_new_type_id(changeset)
|
new_type_id = get_new_type_id(changeset)
|
||||||
|
actor = Map.get(context || %{}, :actor)
|
||||||
|
|
||||||
cond do
|
cond do
|
||||||
# If no current type, allow any change (first assignment)
|
# If no current type, allow any change (first assignment)
|
||||||
|
|
@ -48,13 +49,13 @@ defmodule Mv.MembershipFees.Changes.ValidateSameInterval do
|
||||||
|
|
||||||
# Both types exist - validate intervals match
|
# Both types exist - validate intervals match
|
||||||
true ->
|
true ->
|
||||||
validate_intervals_match(changeset, current_type_id, new_type_id)
|
validate_intervals_match(changeset, current_type_id, new_type_id, actor)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Validates that intervals match when both types exist
|
# Validates that intervals match when both types exist
|
||||||
defp validate_intervals_match(changeset, current_type_id, new_type_id) do
|
defp validate_intervals_match(changeset, current_type_id, new_type_id, actor) do
|
||||||
case get_intervals(current_type_id, new_type_id) do
|
case get_intervals(current_type_id, new_type_id, actor) do
|
||||||
{:ok, current_interval, new_interval} ->
|
{:ok, current_interval, new_interval} ->
|
||||||
if current_interval == new_interval do
|
if current_interval == new_interval do
|
||||||
changeset
|
changeset
|
||||||
|
|
@ -85,11 +86,16 @@ defmodule Mv.MembershipFees.Changes.ValidateSameInterval do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Get intervals for both types
|
# Get intervals for both types (actor required for authorization when resource has policies)
|
||||||
defp get_intervals(current_type_id, new_type_id) do
|
defp get_intervals(current_type_id, new_type_id, actor) do
|
||||||
alias Mv.MembershipFees.MembershipFeeType
|
alias Mv.MembershipFees.MembershipFeeType
|
||||||
|
|
||||||
case {Ash.get(MembershipFeeType, current_type_id), Ash.get(MembershipFeeType, new_type_id)} do
|
opts = if actor, do: [actor: actor], else: []
|
||||||
|
|
||||||
|
case {
|
||||||
|
Ash.get(MembershipFeeType, current_type_id, opts),
|
||||||
|
Ash.get(MembershipFeeType, new_type_id, opts)
|
||||||
|
} do
|
||||||
{{:ok, current_type}, {:ok, new_type}} ->
|
{{:ok, current_type}, {:ok, new_type}} ->
|
||||||
{:ok, current_type.interval, new_type.interval}
|
{:ok, current_type.interval, new_type.interval}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ defmodule Mv.Accounts.User.Validations.EmailNotUsedByOtherMember do
|
||||||
query =
|
query =
|
||||||
Mv.Membership.Member
|
Mv.Membership.Member
|
||||||
|> Ash.Query.filter(email == ^to_string(email))
|
|> Ash.Query.filter(email == ^to_string(email))
|
||||||
|> maybe_exclude_id(exclude_member_id)
|
|> Mv.Helpers.query_exclude_id(exclude_member_id)
|
||||||
|
|
||||||
system_actor = SystemActor.get_system_actor()
|
system_actor = SystemActor.get_system_actor()
|
||||||
opts = Helpers.ash_actor_opts(system_actor)
|
opts = Helpers.ash_actor_opts(system_actor)
|
||||||
|
|
@ -101,7 +101,4 @@ defmodule Mv.Accounts.User.Validations.EmailNotUsedByOtherMember do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_exclude_id(query, nil), do: query
|
|
||||||
defp maybe_exclude_id(query, id), do: Ash.Query.filter(query, id != ^id)
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@ defmodule Mv.EmailSync.Changes.SyncUserEmailToMember do
|
||||||
Modified changeset with email synchronization applied, or original changeset
|
Modified changeset with email synchronization applied, or original changeset
|
||||||
if recursion detected.
|
if recursion detected.
|
||||||
"""
|
"""
|
||||||
|
# Ash 3.12+ calls this to decide whether to run the change in certain contexts.
|
||||||
|
@impl true
|
||||||
|
def has_change?, do: true
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def change(changeset, _opts, context) do
|
def change(changeset, _opts, context) do
|
||||||
# Only recursion protection needed - trigger logic is in `where` clauses
|
# Only recursion protection needed - trigger logic is in `where` clauses
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ defmodule Mv.Helpers do
|
||||||
Provides utilities that are not specific to a single domain or layer.
|
Provides utilities that are not specific to a single domain or layer.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
require Ash.Query
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Converts an actor to Ash options list for authorization.
|
Converts an actor to Ash options list for authorization.
|
||||||
Returns empty list if actor is nil.
|
Returns empty list if actor is nil.
|
||||||
|
|
@ -24,4 +26,22 @@ defmodule Mv.Helpers do
|
||||||
@spec ash_actor_opts(Mv.Accounts.User.t() | nil) :: keyword()
|
@spec ash_actor_opts(Mv.Accounts.User.t() | nil) :: keyword()
|
||||||
def ash_actor_opts(nil), do: []
|
def ash_actor_opts(nil), do: []
|
||||||
def ash_actor_opts(actor) when not is_nil(actor), do: [actor: actor]
|
def ash_actor_opts(actor) when not is_nil(actor), do: [actor: actor]
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns the query unchanged if `exclude_id` is nil; otherwise adds a filter `id != ^exclude_id`.
|
||||||
|
|
||||||
|
Used in uniqueness validations that must exclude the current record (e.g. name uniqueness
|
||||||
|
on update, duplicate association checks). Call with the record's primary key to exclude it
|
||||||
|
from the result set.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
query
|
||||||
|
|> Ash.Query.filter(name == ^name)
|
||||||
|
|> Mv.Helpers.query_exclude_id(current_id)
|
||||||
|
|
||||||
|
"""
|
||||||
|
@spec query_exclude_id(Ash.Query.t(), String.t() | nil) :: Ash.Query.t()
|
||||||
|
def query_exclude_id(query, nil), do: query
|
||||||
|
def query_exclude_id(query, id), do: Ash.Query.filter(query, id != ^id)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ defmodule Mv.Membership.Member.Validations.EmailNotUsedByOtherUser do
|
||||||
query =
|
query =
|
||||||
Mv.Accounts.User
|
Mv.Accounts.User
|
||||||
|> Ash.Query.filter(email == ^email)
|
|> Ash.Query.filter(email == ^email)
|
||||||
|> maybe_exclude_id(exclude_user_id)
|
|> Mv.Helpers.query_exclude_id(exclude_user_id)
|
||||||
|
|
||||||
system_actor = SystemActor.get_system_actor()
|
system_actor = SystemActor.get_system_actor()
|
||||||
opts = Helpers.ash_actor_opts(system_actor)
|
opts = Helpers.ash_actor_opts(system_actor)
|
||||||
|
|
@ -76,7 +76,4 @@ defmodule Mv.Membership.Member.Validations.EmailNotUsedByOtherUser do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_exclude_id(query, nil), do: query
|
|
||||||
defp maybe_exclude_id(query, id), do: Ash.Query.filter(query, id != ^id)
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ alias Mv.MembershipFees.CycleGenerator
|
||||||
|
|
||||||
require Ash.Query
|
require Ash.Query
|
||||||
|
|
||||||
# Create example membership fee types
|
# Create example membership fee types (no admin user yet; skip authorization for bootstrap)
|
||||||
for fee_type_attrs <- [
|
for fee_type_attrs <- [
|
||||||
%{
|
%{
|
||||||
name: "Standard (Jährlich)",
|
name: "Standard (Jährlich)",
|
||||||
|
|
@ -39,7 +39,12 @@ for fee_type_attrs <- [
|
||||||
] do
|
] do
|
||||||
MembershipFeeType
|
MembershipFeeType
|
||||||
|> Ash.Changeset.for_create(:create, fee_type_attrs)
|
|> Ash.Changeset.for_create(:create, fee_type_attrs)
|
||||||
|> Ash.create!(upsert?: true, upsert_identity: :unique_name)
|
|> Ash.create!(
|
||||||
|
upsert?: true,
|
||||||
|
upsert_identity: :unique_name,
|
||||||
|
authorize?: false,
|
||||||
|
domain: Mv.MembershipFees
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
for attrs <- [
|
for attrs <- [
|
||||||
|
|
@ -299,12 +304,12 @@ case Accounts.User
|
||||||
IO.puts("SystemActor will fall back to admin user (#{admin_email})")
|
IO.puts("SystemActor will fall back to admin user (#{admin_email})")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Load all membership fee types for assignment
|
# Load all membership fee types for assignment (admin actor for authorization)
|
||||||
# Sort by name to ensure deterministic order
|
# Sort by name to ensure deterministic order
|
||||||
all_fee_types =
|
all_fee_types =
|
||||||
MembershipFeeType
|
MembershipFeeType
|
||||||
|> Ash.Query.sort(name: :asc)
|
|> Ash.Query.sort(name: :asc)
|
||||||
|> Ash.read!()
|
|> Ash.read!(actor: admin_user_with_role, domain: Mv.MembershipFees)
|
||||||
|> Enum.to_list()
|
|> Enum.to_list()
|
||||||
|
|
||||||
# Create sample members for testing - use upsert to prevent duplicates
|
# Create sample members for testing - use upsert to prevent duplicates
|
||||||
|
|
|
||||||
|
|
@ -54,18 +54,26 @@ defmodule Mv.Membership.MembershipFeeSettingsTest do
|
||||||
|
|
||||||
# Create a valid fee type
|
# Create a valid fee type
|
||||||
{:ok, fee_type} =
|
{:ok, fee_type} =
|
||||||
Ash.create(MembershipFeeType, %{
|
Ash.create(
|
||||||
name: "Test Fee Type #{System.unique_integer([:positive])}",
|
MembershipFeeType,
|
||||||
amount: Decimal.new("100.00"),
|
%{
|
||||||
interval: :yearly
|
name: "Test Fee Type #{System.unique_integer([:positive])}",
|
||||||
})
|
amount: Decimal.new("100.00"),
|
||||||
|
interval: :yearly
|
||||||
|
},
|
||||||
|
actor: actor
|
||||||
|
)
|
||||||
|
|
||||||
# Setting a valid fee type should work
|
# Setting a valid fee type should work
|
||||||
{:ok, updated} =
|
{:ok, updated} =
|
||||||
settings
|
settings
|
||||||
|> Ash.Changeset.for_update(:update_membership_fee_settings, %{
|
|> Ash.Changeset.for_update(
|
||||||
default_membership_fee_type_id: fee_type.id
|
:update_membership_fee_settings,
|
||||||
})
|
%{
|
||||||
|
default_membership_fee_type_id: fee_type.id
|
||||||
|
},
|
||||||
|
actor: actor
|
||||||
|
)
|
||||||
|> Ash.update(actor: actor)
|
|> Ash.update(actor: actor)
|
||||||
|
|
||||||
assert updated.default_membership_fee_type_id == fee_type.id
|
assert updated.default_membership_fee_type_id == fee_type.id
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ defmodule Mv.MembershipFees.Changes.ValidateSameIntervalTest do
|
||||||
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: yearly_type2.id},
|
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: yearly_type2.id},
|
||||||
actor: actor
|
actor: actor
|
||||||
)
|
)
|
||||||
|> ValidateSameInterval.change(%{}, %{})
|
|> ValidateSameInterval.change(%{}, %{actor: actor})
|
||||||
|
|
||||||
assert changeset.valid?
|
assert changeset.valid?
|
||||||
end
|
end
|
||||||
|
|
@ -68,7 +68,7 @@ defmodule Mv.MembershipFees.Changes.ValidateSameIntervalTest do
|
||||||
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: monthly_type.id},
|
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: monthly_type.id},
|
||||||
actor: actor
|
actor: actor
|
||||||
)
|
)
|
||||||
|> ValidateSameInterval.change(%{}, %{})
|
|> ValidateSameInterval.change(%{}, %{actor: actor})
|
||||||
|
|
||||||
refute changeset.valid?
|
refute changeset.valid?
|
||||||
assert %{errors: errors} = changeset
|
assert %{errors: errors} = changeset
|
||||||
|
|
@ -90,7 +90,7 @@ defmodule Mv.MembershipFees.Changes.ValidateSameIntervalTest do
|
||||||
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: yearly_type.id},
|
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: yearly_type.id},
|
||||||
actor: actor
|
actor: actor
|
||||||
)
|
)
|
||||||
|> ValidateSameInterval.change(%{}, %{})
|
|> ValidateSameInterval.change(%{}, %{actor: actor})
|
||||||
|
|
||||||
assert changeset.valid?
|
assert changeset.valid?
|
||||||
end
|
end
|
||||||
|
|
@ -102,7 +102,7 @@ defmodule Mv.MembershipFees.Changes.ValidateSameIntervalTest do
|
||||||
changeset =
|
changeset =
|
||||||
member
|
member
|
||||||
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: nil}, actor: actor)
|
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: nil}, actor: actor)
|
||||||
|> ValidateSameInterval.change(%{}, %{})
|
|> ValidateSameInterval.change(%{}, %{actor: actor})
|
||||||
|
|
||||||
refute changeset.valid?
|
refute changeset.valid?
|
||||||
assert %{errors: errors} = changeset
|
assert %{errors: errors} = changeset
|
||||||
|
|
@ -120,7 +120,7 @@ defmodule Mv.MembershipFees.Changes.ValidateSameIntervalTest do
|
||||||
changeset =
|
changeset =
|
||||||
member
|
member
|
||||||
|> Ash.Changeset.for_update(:update_member, %{first_name: "New Name"}, actor: actor)
|
|> Ash.Changeset.for_update(:update_member, %{first_name: "New Name"}, actor: actor)
|
||||||
|> ValidateSameInterval.change(%{}, %{})
|
|> ValidateSameInterval.change(%{}, %{actor: actor})
|
||||||
|
|
||||||
assert changeset.valid?
|
assert changeset.valid?
|
||||||
end
|
end
|
||||||
|
|
@ -136,7 +136,7 @@ defmodule Mv.MembershipFees.Changes.ValidateSameIntervalTest do
|
||||||
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: quarterly_type.id},
|
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: quarterly_type.id},
|
||||||
actor: actor
|
actor: actor
|
||||||
)
|
)
|
||||||
|> ValidateSameInterval.change(%{}, %{})
|
|> ValidateSameInterval.change(%{}, %{actor: actor})
|
||||||
|
|
||||||
error = Enum.find(changeset.errors, &(&1.field == :membership_fee_type_id))
|
error = Enum.find(changeset.errors, &(&1.field == :membership_fee_type_id))
|
||||||
assert error.message =~ "yearly"
|
assert error.message =~ "yearly"
|
||||||
|
|
@ -175,7 +175,7 @@ defmodule Mv.MembershipFees.Changes.ValidateSameIntervalTest do
|
||||||
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: type2.id},
|
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: type2.id},
|
||||||
actor: actor
|
actor: actor
|
||||||
)
|
)
|
||||||
|> ValidateSameInterval.change(%{}, %{})
|
|> ValidateSameInterval.change(%{}, %{actor: actor})
|
||||||
|
|
||||||
refute changeset.valid?,
|
refute changeset.valid?,
|
||||||
"Should prevent change from #{interval1} to #{interval2}"
|
"Should prevent change from #{interval1} to #{interval2}"
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ defmodule Mv.MembershipFees.MembershipFeeCycleTest do
|
||||||
member = create_member(%{membership_fee_type_id: fee_type.id}, actor)
|
member = create_member(%{membership_fee_type_id: fee_type.id}, actor)
|
||||||
cycle = create_cycle(member, fee_type, %{status: :paid}, actor)
|
cycle = create_cycle(member, fee_type, %{status: :paid}, actor)
|
||||||
|
|
||||||
assert {:ok, updated} = Ash.update(cycle, %{}, action: :mark_as_unpaid)
|
assert {:ok, updated} = Ash.update(cycle, %{}, actor: actor, action: :mark_as_unpaid)
|
||||||
assert updated.status == :unpaid
|
assert updated.status == :unpaid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -175,7 +175,7 @@ defmodule Mv.MembershipFees.MembershipFeeCycleTest do
|
||||||
member = create_member(%{membership_fee_type_id: fee_type.id}, actor)
|
member = create_member(%{membership_fee_type_id: fee_type.id}, actor)
|
||||||
cycle = create_cycle(member, fee_type, %{status: :suspended}, actor)
|
cycle = create_cycle(member, fee_type, %{status: :suspended}, actor)
|
||||||
|
|
||||||
assert {:ok, updated} = Ash.update(cycle, %{}, action: :mark_as_unpaid)
|
assert {:ok, updated} = Ash.update(cycle, %{}, actor: actor, action: :mark_as_unpaid)
|
||||||
assert updated.status == :unpaid
|
assert updated.status == :unpaid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -155,9 +155,13 @@ defmodule Mv.MembershipFees.MembershipFeeTypeIntegrationTest do
|
||||||
{:ok, settings} = Mv.Membership.get_settings()
|
{:ok, settings} = Mv.Membership.get_settings()
|
||||||
|
|
||||||
settings
|
settings
|
||||||
|> Ash.Changeset.for_update(:update_membership_fee_settings, %{
|
|> Ash.Changeset.for_update(
|
||||||
default_membership_fee_type_id: fee_type.id
|
:update_membership_fee_settings,
|
||||||
})
|
%{
|
||||||
|
default_membership_fee_type_id: fee_type.id
|
||||||
|
},
|
||||||
|
actor: actor
|
||||||
|
)
|
||||||
|> Ash.update!(actor: actor)
|
|> Ash.update!(actor: actor)
|
||||||
|
|
||||||
# Try to delete
|
# Try to delete
|
||||||
|
|
@ -176,9 +180,13 @@ defmodule Mv.MembershipFees.MembershipFeeTypeIntegrationTest do
|
||||||
{:ok, settings} = Mv.Membership.get_settings()
|
{:ok, settings} = Mv.Membership.get_settings()
|
||||||
|
|
||||||
settings
|
settings
|
||||||
|> Ash.Changeset.for_update(:update_membership_fee_settings, %{
|
|> Ash.Changeset.for_update(
|
||||||
default_membership_fee_type_id: fee_type.id
|
:update_membership_fee_settings,
|
||||||
})
|
%{
|
||||||
|
default_membership_fee_type_id: fee_type.id
|
||||||
|
},
|
||||||
|
actor: actor
|
||||||
|
)
|
||||||
|> Ash.update!(actor: actor)
|
|> Ash.update!(actor: actor)
|
||||||
|
|
||||||
# Create a member without explicitly setting membership_fee_type_id
|
# Create a member without explicitly setting membership_fee_type_id
|
||||||
|
|
|
||||||
|
|
@ -264,9 +264,13 @@ defmodule Mv.MembershipFees.MembershipFeeTypeTest do
|
||||||
{:ok, settings} = Mv.Membership.get_settings()
|
{:ok, settings} = Mv.Membership.get_settings()
|
||||||
|
|
||||||
settings
|
settings
|
||||||
|> Ash.Changeset.for_update(:update_membership_fee_settings, %{
|
|> Ash.Changeset.for_update(
|
||||||
default_membership_fee_type_id: fee_type.id
|
:update_membership_fee_settings,
|
||||||
})
|
%{
|
||||||
|
default_membership_fee_type_id: fee_type.id
|
||||||
|
},
|
||||||
|
actor: actor
|
||||||
|
)
|
||||||
|> Ash.update!(actor: actor)
|
|> Ash.update!(actor: actor)
|
||||||
|
|
||||||
# Try to delete
|
# Try to delete
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue