feat: read projection sourced from the register in Objecten (closes #153) #155

Merged
not merged 12 commits from feat/153-projection-sourced-from-objecten into main 2026-09-01 07:26:34 +00:00
4 changed files with 12 additions and 11 deletions
Showing only changes of commit b496ac9477 - Show all commits
@@ -84,11 +84,12 @@ app.MapPost("/admin/rebuild", async (NotificationProjector projector, Cancellati
await app.RunAsync();
/// <summary>The NRC notification body, as Open Notificaties POSTs it. Only the fields the
/// projection needs are bound; <c>aanmaakdatum</c>/<c>kenmerken</c> are ignored for the minimal slice.</summary>
public sealed record NotificationDto(string Kanaal, string Resource, string Actie, Uri ResourceUrl, Uri? HoofdObject = null)
/// <summary>The NRC notification body, as Open Notificaties POSTs it. Only the fields the projector
/// needs are bound; <c>aanmaakdatum</c>, <c>kenmerken</c> and <c>hoofdObject</c> are ignored for a
/// register write hoofdObject is the same object as resourceUrl (ADR-0030).</summary>
public sealed record NotificationDto(string Kanaal, string Resource, string Actie, Uri ResourceUrl)
{
public Notification ToNotification() => new(Kanaal, Resource, Actie, ResourceUrl, HoofdObject);
public Notification ToNotification() => new(Kanaal, Resource, Actie, ResourceUrl);
}
public partial class Program
@@ -16,15 +16,15 @@ public sealed record Notification(
string Kanaal,
string Resource,
string Actie,
Uri ResourceUrl,
Uri? HoofdObject = null)
Uri ResourceUrl)
{
/// <summary>A register record written to Objecten — <c>create</c> on submit, <c>update</c> on
/// approval, since the ACL upserts the same object for a registration (§8.6).</summary>
public bool IsRegisterRecordWritten =>
Kanaal == "objecten" && Resource == "object" && Actie is "create" or "update";
/// <summary>The object holding the register record. Objecten sets both fields to the object;
/// <c>hoofdObject</c> is the main resource by definition, so prefer it.</summary>
public Uri ObjectUrl => HoofdObject ?? ResourceUrl;
/// <summary>The object holding the register record. For a <c>resource: object</c> notification
/// Objecten sends the object as both <c>hoofdObject</c> and <c>resourceUrl</c> — the object is
/// the main resource — so the notification's own <c>hoofdObject</c> is not modelled.</summary>
public Uri ObjectUrl => ResourceUrl;
}
@@ -22,7 +22,7 @@ public sealed class NotificationProjectorTests
private Notification RecordWritten(string actie = "create", string url = ObjectUrl, string status = RegistrationStatus.Ingediend, string zaakId = ZaakId)
{
_acl.Records[url] = new RegisterRecord(zaakId, status, "REG-2026-0001");
return new Notification("objecten", "object", actie, new Uri(url), new Uri(url));
return new Notification("objecten", "object", actie, new Uri(url));
}
[Fact]
@@ -28,7 +28,7 @@ public sealed class RegisterProjectieBijwerkenSteps
// The ACL upserts one object per registration, so submit and approval share an object URL.
var objectUrl = ObjectBase + id;
_register.Records[objectUrl] = new RegisterRecord(id, status, "REG-" + id);
_notification = new Notification("objecten", "object", "create", new Uri(objectUrl), new Uri(objectUrl));
_notification = new Notification("objecten", "object", "create", new Uri(objectUrl));
}
[Given("the register notification is delivered to the event subscriber")]