From 3b3a44b17725bb58c510eb8ac8b36fd8e40f2f03 Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Thu, 23 Jul 2026 11:52:58 +0200 Subject: [PATCH] test(domain): store finds inscriptions due for a herregistratie reminder (refs #18) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- services/domain/Big.Application/Ports.cs | 7 ++++++ .../InMemoryRegistrationStore.cs | 4 ++++ services/domain/Big.Tests/Fakes.cs | 5 ++++ .../InMemoryRegistrationStoreTests.cs | 23 +++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/services/domain/Big.Application/Ports.cs b/services/domain/Big.Application/Ports.cs index 08fdbde..70ec270 100644 --- a/services/domain/Big.Application/Ports.cs +++ b/services/domain/Big.Application/Ports.cs @@ -107,6 +107,13 @@ public interface IRegistrationStore /// registration, or null if they have none in flight. Lets the self-service portal resume /// an existing registration after a refresh (S-26); terminal registrations are not resumed. Task FindOpenByBsnAsync(string bsn, CancellationToken ct = default); + + /// The inscriptions whose herregistratie reminder is due as of and + /// not yet sent — the herregistratie reminder sweep's candidate set (S-17). The predicate is the + /// aggregate's own rule, so the store never + /// duplicates the herregistratie policy. + Task> FindDueForHerregistratieReminderAsync( + DateTimeOffset asOf, CancellationToken ct = default); } /// diff --git a/services/domain/Big.Infrastructure/InMemoryRegistrationStore.cs b/services/domain/Big.Infrastructure/InMemoryRegistrationStore.cs index 086dc81..75e630c 100644 --- a/services/domain/Big.Infrastructure/InMemoryRegistrationStore.cs +++ b/services/domain/Big.Infrastructure/InMemoryRegistrationStore.cs @@ -26,4 +26,8 @@ public sealed class InMemoryRegistrationStore : IRegistrationStore public Task FindOpenByBsnAsync(string bsn, CancellationToken ct = default) => Task.FromResult(_byId.Values.FirstOrDefault(r => r.Bsn == bsn && r.Status is RegistrationStatus.Ingediend or RegistrationStatus.InBehandeling)); + + public Task> FindDueForHerregistratieReminderAsync( + DateTimeOffset asOf, CancellationToken ct = default) + => Task.FromResult>([]); // RED stub } diff --git a/services/domain/Big.Tests/Fakes.cs b/services/domain/Big.Tests/Fakes.cs index c9ff30f..623c331 100644 --- a/services/domain/Big.Tests/Fakes.cs +++ b/services/domain/Big.Tests/Fakes.cs @@ -26,6 +26,11 @@ internal sealed class FakeRegistrationStore : IRegistrationStore => Task.FromResult(_byId.Values.FirstOrDefault(r => r.Bsn == bsn && r.Status is RegistrationStatus.Ingediend or RegistrationStatus.InBehandeling)); + public Task> FindDueForHerregistratieReminderAsync( + DateTimeOffset asOf, CancellationToken ct = default) + => Task.FromResult>( + _byId.Values.Where(r => r.HerregistratieReminderDue(asOf)).ToList()); + public void Seed(Registration registration) => _byId[registration.Id] = registration; } diff --git a/services/domain/Big.Tests/InMemoryRegistrationStoreTests.cs b/services/domain/Big.Tests/InMemoryRegistrationStoreTests.cs index 284da9f..dc21fa7 100644 --- a/services/domain/Big.Tests/InMemoryRegistrationStoreTests.cs +++ b/services/domain/Big.Tests/InMemoryRegistrationStoreTests.cs @@ -96,4 +96,27 @@ public class InMemoryRegistrationStoreTests Assert.Null(await store.FindOpenByBsnAsync("123456782")); } + + [Fact] + public async Task Finds_only_the_inscriptions_due_for_a_herregistratie_reminder() + { + var now = new DateTimeOffset(2026, 7, 23, 0, 0, 0, TimeSpan.Zero); + var store = new InMemoryRegistrationStore(); + + var due = Registration.Submit("123456782"); + due.AttachZaak(new Uri("http://openzaak/zaken/api/v1/zaken/abc")); + due.Approve(now - Registration.HerregistratieGeldigheid + Registration.Herinneringstermijn); + await store.SaveAsync(due); + + var freshlyInscribed = Registration.Submit("111111110"); + freshlyInscribed.AttachZaak(new Uri("http://openzaak/zaken/api/v1/zaken/def")); + freshlyInscribed.Approve(now); + await store.SaveAsync(freshlyInscribed); + + await store.SaveAsync(Registration.Submit("222222222")); // still INGEDIEND — never inscribed + + var result = await store.FindDueForHerregistratieReminderAsync(now); + + Assert.Equal([due.Id], result.Select(r => r.Id).ToArray()); + } }