feat(member): add period-scoped unpaid-cycle payment-aging model

Counts each member's unpaid billing cycles that fall inside the selected
period. Cycle boundaries are member-relative — derived from each member's
fee-type interval — so "the current cycle" spans different calendar dates
per member.
This commit is contained in:
Simon 2026-07-10 16:27:14 +02:00
parent 4b647c21e7
commit 95ef3177ac
8 changed files with 456 additions and 0 deletions

View file

@ -717,6 +717,25 @@ defmodule Mv.Membership.Member do
constraints one_of: [:unpaid, :paid, :suspended]
end
calculate :unpaid_cycle_count,
:integer,
expr(
count(membership_fee_cycles,
query: [
filter:
expr(
status == :unpaid and
(is_nil(^arg(:period_from)) or cycle_end >= ^arg(:period_from)) and
(is_nil(^arg(:period_to)) or cycle_end <= ^arg(:period_to))
)
]
)
) do
description "Count of the member's unpaid cycles whose cycle_end is within the given period"
argument :period_from, :date, allow_nil?: true
argument :period_to, :date, allow_nil?: true
end
calculate :overdue_count, :integer do
description "Count of unpaid cycles that have already ended (cycle_end < today)"
# Automatically load cycles with all attributes and membership_fee_type