Files
CCMA/tests/test_housekeeper.py
T
2026-06-26 21:57:11 +02:00

141 lines
5.2 KiB
Python

import json
from datetime import date
from ccma.domain.models import ContributionData
from ccma.services.housekeeper import Housekeeper, HousekeeperSettings
from ccma.storage.repository import MemberRepository
def test_housekeeper_reports_initial_payment_and_open_claims(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
member = repository.create_member(first_name="Test", last_name="Person", birth_date="1990-01-01")
member.status = "accepted_pending_payment"
member.accepted_at = "2026-01-01"
repository.save_member(member)
repository.save_contributions(
member.member_id,
ContributionData(
claims=[
{
"claim_id": "claim-1",
"title": "Mitgliedsbeitrag 2026",
"amount": "150.00",
"due_date": "2026-01-31",
"status": "open",
}
]
),
)
findings = Housekeeper(repository).run(today=date(2026, 2, 10))
assert {finding.code for finding in findings} == {
"initial_payment_overdue",
"claim_overdue",
"reminder_due",
}
def test_housekeeper_reports_birthdays_before_today_and_after(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
dates = ("1990-06-20", "1990-06-21", "1990-06-22")
for index, birth_date in enumerate(dates):
member = repository.create_member(
first_name=f"Birthday{index}",
last_name="Member",
birth_date=birth_date,
)
member.status = "active"
repository.save_member(member)
settings = HousekeeperSettings.from_values(
birthday_days_before=2,
birthday_days_after=2,
anniversary_days_before=0,
anniversary_days_after=0,
anniversary_intervals="1Y",
)
findings = [
finding
for finding in Housekeeper(repository, settings).run(today=date(2026, 6, 21))
if finding.code == "birthday"
]
assert {finding.title for finding in findings} == {
"Birthday0 Member hatte vor 1 Tag Geburtstag",
"Birthday1 Member hat heute Geburtstag",
"Birthday2 Member hat in 1 Tag Geburtstag",
}
def test_housekeeper_reports_day_month_and_year_anniversaries(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
starts = ("2026-05-22", "2026-04-21", "2025-06-21", "2016-06-22")
for index, started_at in enumerate(starts):
member = repository.create_member(first_name=f"Anniversary{index}", last_name="Member")
member.status = "active"
member.membership_started_at = started_at
repository.save_member(member)
settings = HousekeeperSettings.from_values(
birthday_days_before=0,
birthday_days_after=0,
anniversary_days_before=2,
anniversary_days_after=2,
anniversary_intervals="30D;2M;1Y;10Y",
)
findings = [
finding
for finding in Housekeeper(repository, settings).run(today=date(2026, 6, 21))
if finding.code == "membership_anniversary"
]
assert {finding.title for finding in findings} == {
"Anniversary0 Member hat heute 30-Tage-Mitgliedsjubiläum",
"Anniversary1 Member hat heute 2-Monats-Mitgliedsjubiläum",
"Anniversary2 Member hat heute 1-jähriges Mitgliedsjubiläum",
"Anniversary3 Member hat in 1 Tag 10-jähriges Mitgliedsjubiläum",
}
def test_housekeeper_reports_invalid_member_dates(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
member = repository.create_member(first_name="Broken", last_name="Date")
member_path = repository.members_root / member.member_id / "member.json"
raw = json.loads(member_path.read_text(encoding="utf-8"))
raw["person"]["birth_date"] = "31/12/2000"
member_path.write_text(json.dumps(raw), encoding="utf-8")
findings = Housekeeper(repository).run(today=date(2026, 6, 21))
invalid = [finding for finding in findings if finding.code == "invalid_member_dates"]
assert len(invalid) == 1
assert invalid[0].member_id == member.member_id
assert "Geburtsdatum" in invalid[0].detail
def test_housekeeper_can_treat_selected_member_fields_as_optional(tmp_path) -> None:
repository = MemberRepository(tmp_path)
repository.initialize()
member = repository.create_member(first_name="Optional", last_name="Fields")
member.status = "active"
repository.save_member(member)
settings = HousekeeperSettings.from_values(
birthday_days_before=0,
birthday_days_after=0,
anniversary_days_before=0,
anniversary_days_after=0,
anniversary_intervals="1Y",
optional_member_fields=("nickname", "email", "phone", "birth_date"),
)
findings = Housekeeper(repository, settings).run(today=date(2026, 6, 21))
codes = {finding.code for finding in findings}
assert "missing_birth_date" not in codes
assert "missing_member_field:nickname" not in codes
assert "missing_member_field:email" not in codes
assert "missing_member_field:phone" not in codes
assert "missing_member_field:street" in codes