feat: add scriptable housekeeper rule engine

This commit is contained in:
Marcel Peterkau
2026-06-21 17:43:04 +02:00
parent e63abbae81
commit 4bc1a8a200
18 changed files with 936 additions and 207 deletions
@@ -0,0 +1,50 @@
from ccma.domain.dates import DateValidationError, parse_iso_date
from ccma.rules.api import RuleContext, task
from ccma.rules.scripts._shared import relative_title
RULE_ID = "membership-anniversary"
ORDER = 30
def evaluate(context: RuleContext):
member = context.member
try:
started_at = parse_iso_date(member.membership_started_at, "Mitglied seit")
except DateValidationError:
return []
if not started_at:
return []
actions = []
for interval in context.settings.anniversary_intervals:
try:
target = interval.target_date(started_at)
except (OverflowError, ValueError):
continue
delta = (target - context.today).days
if (
delta > context.settings.anniversary_days_before
or delta < -context.settings.anniversary_days_after
):
continue
occasion = _anniversary_name(interval)
actions.append(
task(
rule_id=RULE_ID,
member=member,
key_suffix=f"{interval.value}{interval.unit}",
severity="info",
title=relative_title(member.display_name, delta, occasion),
detail=f"Mitglied seit {started_at:%d.%m.%Y}.",
due_date=target,
code="membership_anniversary",
)
)
return actions
def _anniversary_name(interval):
if interval.unit == "D":
return f"{interval.value}-Tage-Mitgliedsjubiläum"
if interval.unit == "M":
return f"{interval.value}-Monats-Mitgliedsjubiläum"
return f"{interval.value}-jähriges Mitgliedsjubiläum"