mitgliederverwaltung/test/membership_fees/membership_fee_cycle_test.exs

207 lines
6.7 KiB
Elixir

defmodule Mv.MembershipFees.MembershipFeeCycleTest do
@moduledoc """
Tests for MembershipFeeCycle resource, focusing on status management actions.
"""
use Mv.DataCase, async: true
alias Mv.MembershipFees.MembershipFeeCycle
alias Mv.MembershipFees.MembershipFeeType
alias Mv.Membership.Member
# Helper to create a membership fee type
defp create_fee_type(attrs) do
default_attrs = %{
name: "Test Fee Type #{System.unique_integer([:positive])}",
amount: Decimal.new("50.00"),
interval: :yearly
}
attrs = Map.merge(default_attrs, attrs)
MembershipFeeType
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
end
# Helper to create a member
defp create_member(attrs) do
default_attrs = %{
first_name: "Test",
last_name: "Member",
email: "test.member.#{System.unique_integer([:positive])}@example.com"
}
attrs = Map.merge(default_attrs, attrs)
Member
|> Ash.Changeset.for_create(:create_member, attrs)
|> Ash.create!()
end
# Helper to create a cycle
defp create_cycle(member, fee_type, attrs) do
default_attrs = %{
cycle_start: ~D[2024-01-01],
amount: Decimal.new("50.00"),
member_id: member.id,
membership_fee_type_id: fee_type.id
}
attrs = Map.merge(default_attrs, attrs)
MembershipFeeCycle
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
end
describe "status defaults" do
test "status defaults to :unpaid when creating a cycle" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
cycle =
MembershipFeeCycle
|> Ash.Changeset.for_create(:create, %{
cycle_start: ~D[2024-01-01],
amount: Decimal.new("50.00"),
member_id: member.id,
membership_fee_type_id: fee_type.id
})
|> Ash.create!()
assert cycle.status == :unpaid
end
end
describe "mark_as_paid" do
test "sets status to :paid" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
cycle = create_cycle(member, fee_type, %{status: :unpaid})
assert {:ok, updated} = Ash.update(cycle, %{}, action: :mark_as_paid)
assert updated.status == :paid
end
test "can set notes when marking as paid" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
cycle = create_cycle(member, fee_type, %{status: :unpaid})
assert {:ok, updated} =
Ash.update(cycle, %{notes: "Payment received via bank transfer"},
action: :mark_as_paid
)
assert updated.status == :paid
assert updated.notes == "Payment received via bank transfer"
end
test "can change from suspended to paid" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
cycle = create_cycle(member, fee_type, %{status: :suspended})
assert {:ok, updated} = Ash.update(cycle, %{}, action: :mark_as_paid)
assert updated.status == :paid
end
end
describe "mark_as_suspended" do
test "sets status to :suspended" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
cycle = create_cycle(member, fee_type, %{status: :unpaid})
assert {:ok, updated} = Ash.update(cycle, %{}, action: :mark_as_suspended)
assert updated.status == :suspended
end
test "can set notes when marking as suspended" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
cycle = create_cycle(member, fee_type, %{status: :unpaid})
assert {:ok, updated} =
Ash.update(cycle, %{notes: "Waived due to special circumstances"},
action: :mark_as_suspended
)
assert updated.status == :suspended
assert updated.notes == "Waived due to special circumstances"
end
test "can change from paid to suspended" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
cycle = create_cycle(member, fee_type, %{status: :paid})
assert {:ok, updated} = Ash.update(cycle, %{}, action: :mark_as_suspended)
assert updated.status == :suspended
end
end
describe "mark_as_unpaid" do
test "sets status to :unpaid" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
cycle = create_cycle(member, fee_type, %{status: :paid})
assert {:ok, updated} = Ash.update(cycle, %{}, action: :mark_as_unpaid)
assert updated.status == :unpaid
end
test "can set notes when marking as unpaid" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
cycle = create_cycle(member, fee_type, %{status: :paid})
assert {:ok, updated} =
Ash.update(cycle, %{notes: "Payment was reversed"}, action: :mark_as_unpaid)
assert updated.status == :unpaid
assert updated.notes == "Payment was reversed"
end
test "can change from suspended to unpaid" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
cycle = create_cycle(member, fee_type, %{status: :suspended})
assert {:ok, updated} = Ash.update(cycle, %{}, action: :mark_as_unpaid)
assert updated.status == :unpaid
end
end
describe "status transitions" do
test "all status transitions are allowed" do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
# unpaid -> paid
cycle1 = create_cycle(member, fee_type, %{status: :unpaid})
assert {:ok, c1} = Ash.update(cycle1, %{}, action: :mark_as_paid)
assert c1.status == :paid
# paid -> suspended
assert {:ok, c2} = Ash.update(c1, %{}, action: :mark_as_suspended)
assert c2.status == :suspended
# suspended -> unpaid
assert {:ok, c3} = Ash.update(c2, %{}, action: :mark_as_unpaid)
assert c3.status == :unpaid
# unpaid -> suspended
assert {:ok, c4} = Ash.update(c3, %{}, action: :mark_as_suspended)
assert c4.status == :suspended
# suspended -> paid
assert {:ok, c5} = Ash.update(c4, %{}, action: :mark_as_paid)
assert c5.status == :paid
# paid -> unpaid
assert {:ok, c6} = Ash.update(c5, %{}, action: :mark_as_unpaid)
assert c6.status == :unpaid
end
end
end