Statistics: member stats independent of fee type

This commit is contained in:
Moritz 2026-02-12 17:42:30 +01:00 committed by moritz
parent 98af2b77ee
commit 490dced8c8
3 changed files with 272 additions and 147 deletions

View file

@ -121,9 +121,14 @@ defmodule Mv.Statistics do
MembershipFeeCycle
|> Ash.Query.filter(expr(cycle_start >= ^first_day and cycle_start <= ^last_day))
opts_with_domain = Keyword.put(opts, :domain, MembershipFees)
query = maybe_filter_by_fee_type(query, opts)
# Only pass actor and domain to Ash.read; fee_type_id is only for our filter above
opts_for_read =
opts
|> Keyword.drop([:fee_type_id])
|> Keyword.put(:domain, MembershipFees)
case Ash.read(query, opts_with_domain) do
case Ash.read(query, opts_for_read) do
{:ok, cycles} -> cycle_totals_from_cycles(cycles)
{:error, _} -> zero_cycle_totals()
end
@ -158,6 +163,24 @@ defmodule Mv.Statistics do
}
end
defp maybe_filter_by_fee_type(query, opts) do
case Keyword.get(opts, :fee_type_id) do
nil ->
query
id when is_binary(id) ->
# Only apply filter for valid UUID strings (e.g. from form/URL)
if Ecto.UUID.cast(id) != :error do
Ash.Query.filter(query, expr(membership_fee_type_id == ^id))
else
query
end
id ->
Ash.Query.filter(query, expr(membership_fee_type_id == ^id))
end
end
@doc """
Returns the sum of amount for all cycles with status :unpaid.
"""
@ -167,9 +190,14 @@ defmodule Mv.Statistics do
MembershipFeeCycle
|> Ash.Query.filter(expr(status == :unpaid))
opts_with_domain = Keyword.put(opts, :domain, MembershipFees)
query = maybe_filter_by_fee_type(query, opts)
case Ash.read(query, opts_with_domain) do
opts_for_read =
opts
|> Keyword.drop([:fee_type_id])
|> Keyword.put(:domain, MembershipFees)
case Ash.read(query, opts_for_read) do
{:ok, cycles} ->
Enum.reduce(cycles, Decimal.new(0), fn c, acc -> Decimal.add(acc, c.amount) end)