feat(events): formal end date for recurring series

Add EventSeries.until: an explicit series end that caps occurrence
generation (whichever comes first — it, the generation horizon, or the
rule's own COUNT/UNTIL). Blank means open-ended. Surface it in the admin.
100% coverage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 19:22:48 +02:00
parent c535e5dc8c
commit 2653dd6d08
5 changed files with 45 additions and 3 deletions

View File

@@ -22,7 +22,14 @@ def horizon():
def occurrence_datetimes(series, until):
"""Expand the series' RRULE from its anchor up to ``until``, minus EXDATEs."""
"""Expand the series' RRULE from its anchor up to ``until``, minus EXDATEs.
``until`` is the generation horizon; the series' own ``until`` (its formal
end) further caps it, whichever comes first.
"""
if series.until is not None and series.until < until:
until = series.until
rule = rrulestr(series.rrule, dtstart=series.dtstart)
excluded = set(series.excluded_dates)