feat(domain): herregistratie reminder sweep on a Quartz cron (S-17, closes #18) #121

Merged
not merged 9 commits from feat/18-herregistratie-reminder-sweep into main 2026-07-23 10:31:57 +00:00
9 Commits
Author SHA1 Message Date
not ccb268bdd5 docs: ADR-0022 + demo note + backlog sync for the herregistratie sweep (refs #18)
CI / lint (pull_request) Successful in 4m27s
CI / build (pull_request) Successful in 1m11s
CI / unit (pull_request) Successful in 1m17s
CI / frontend (pull_request) Successful in 2m53s
CI / mutation (pull_request) Successful in 5m59s
CI / verify-stack (pull_request) Successful in 8m52s
ADR-0022 records using Quartz.NET for time-triggered fleet sweeps (pumps stay as
queue-drainers); demo-script and BACKLOG describe S-17's outcome.

refs #18
2026-07-23 12:01:36 +02:00
not b5085dc978 refactor(domain): herregistratie reminder lead time to 90 days per S-17 spec (refs #18)
refs #18
2026-07-23 12:01:36 +02:00
not f49cad1900 feat(domain): Quartz cron job fires the herregistratie sweep; expose deadline on read (refs #18)
HerregistratieReminderJob (Quartz IJob) fires HerregistratieReminderSweep on a
daily cron wired in Big.Api (overridable via Quartz__Cron), and logs how many
reminders went out. Quartz.NET is used for this time-triggered fleet sweep,
distinct from the queue-draining pumps (ADR-0022). GET /registrations/{id} now
returns herregistratieVoor + herregistratieReminderVerstuurd. The scheduling
shell is excluded from mutation, mirroring the pumps.

refs #18
2026-07-23 11:58:42 +02:00
not 1e27819386 feat(domain): HerregistratieReminderSweep reminds + persists due inscriptions (refs #18)
refs #18
2026-07-23 11:55:08 +02:00
not 3c841c04bd test(domain): herregistratie reminder sweep flags + returns due inscriptions (refs #18)
HerregistratieReminderSweep reminds every due inscription, persists the flag so a
re-fire is a no-op, and returns the reminded ids. Stubbed to an empty result so
the new tests fail; green implements the sweep. Adds a FixedClock TimeProvider
fake so the sweep is deterministic without a testing package.

refs #18
2026-07-23 11:54:38 +02:00
not 27fdde5551 feat(domain): FindDueForHerregistratieReminderAsync filters on the reminder-due rule (refs #18)
refs #18
2026-07-23 11:53:16 +02:00
not 3b3a44b177 test(domain): store finds inscriptions due for a herregistratie reminder (refs #18)
New IRegistrationStore.FindDueForHerregistratieReminderAsync — the sweep's
candidate set. The production store is stubbed to an empty list so the new test
fails; the green commit filters on the aggregate's own reminder-due rule.

refs #18
2026-07-23 11:52:58 +02:00
not 22215865b3 feat(domain): record inscription date + herregistratie reminder-due rule (refs #18)
Approve stores the inscription moment; HerregistratieVoor derives the deadline
(inscription + 5-year validity); HerregistratieReminderDue(asOf) is true once the
16-week window before the deadline opens for a still-un-reminded inscription;
MarkHerregistratieReminderVerstuurd is idempotent and guards against reminding a
non-inscribed registration.

refs #18
2026-07-23 11:51:47 +02:00
not dc532dee00 test(domain): herregistratie inscription date + reminder-due rule (refs #18)
The Registration aggregate gains the herregistratie clock: Approve now records
the inscription moment, from which the herregistratie deadline and a
reminder-due rule are derived. Members are stubbed so the suite compiles and the
new assertions fail; the green commit implements them. Approve's signature gains
the inscription moment (callers now supply 'now' from an injected TimeProvider).

refs #18
2026-07-23 11:51:11 +02:00