mirror of
https://git.hiabuto.net/C3MA/CCMA.git
synced 2026-08-25 23:15:18 +02:00
Add individually agreed membership fees (contribution overrides)
Members are sometimes given a fee that deviates from the regular schedule -- e.g. a reduced rate for students -- for a specific period. Add a per-member "Beitrag" tab where such deviations can be recorded with a month-granular date range (Ab/Bis), a mandatory reason, and either a fixed annual amount or a percentage discount off whichever base rate is in effect at the time. Data model: ContributionData gets a contribution_overrides list, each entry validated (month format, Bis >= Ab, non-overlapping ranges per member, reason required) and CRUD'd through the repository (record/update/delete/get_contribution_override), consistent with how donations already work. Integration: contribution_claims.py now computes each membership-fee claim's amount month by month instead of a single rate for the whole billing period, picking up whichever override (if any) covers each individual month. That handles an override starting or ending mid period correctly (e.g. a semiannual payer whose discount begins in March) without changing behavior for members without overrides. Already-created claims are never recalculated retroactively, matching how changes to the global contribution rates already behave. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
44228dd7dd
commit
2484a1631d
@@ -7,9 +7,11 @@ from ccma.domain.dates import (
|
||||
age_label,
|
||||
calculate_age,
|
||||
format_date_for_display,
|
||||
format_month_for_display,
|
||||
normalize_date_input,
|
||||
parse_date_input,
|
||||
parse_iso_date,
|
||||
parse_month_input,
|
||||
validate_birth_date,
|
||||
validate_member_dates,
|
||||
)
|
||||
@@ -68,6 +70,25 @@ def test_member_dates_must_be_chronological() -> None:
|
||||
)
|
||||
|
||||
|
||||
def test_month_input_accepts_german_and_iso_formats() -> None:
|
||||
assert parse_month_input("03.2026", "Ab") == "2026-03"
|
||||
assert parse_month_input("2026-03", "Ab") == "2026-03"
|
||||
assert parse_month_input("", "Ab") == ""
|
||||
with pytest.raises(DateValidationError, match="erforderlich"):
|
||||
parse_month_input("", "Ab", allow_empty=False)
|
||||
with pytest.raises(DateValidationError):
|
||||
parse_month_input("13.2026", "Ab")
|
||||
with pytest.raises(DateValidationError):
|
||||
parse_month_input("2026-03-15", "Ab")
|
||||
|
||||
|
||||
def test_month_display_uses_system_pattern(monkeypatch) -> None:
|
||||
monkeypatch.setattr("ccma.domain.dates.system_date_pattern", lambda: "%d.%m.%Y")
|
||||
assert format_month_for_display("2026-03") == "03.2026"
|
||||
monkeypatch.setattr("ccma.domain.dates.system_date_pattern", lambda: "%Y-%m-%d")
|
||||
assert format_month_for_display("2026-03") == "2026-03"
|
||||
|
||||
|
||||
def test_age_calculation_and_label() -> None:
|
||||
today = date(2026, 6, 21)
|
||||
assert calculate_age(date(2000, 6, 21), today) == 26
|
||||
|
||||
Reference in New Issue
Block a user