namespace EventSubscriber.Application; /// /// An inbound NRC (Open Notificaties) notification, as Open Notificaties POSTs it to an /// abonnement callback. Only the fields the projection needs are modelled; the full ZGW /// "Notificatie" resource also carries aanmaakdatum and kenmerken which the /// minimal projection ignores (bsn is deferred — see ADR-0008). For a zaken/zaak/create /// notification hoofdObject and resourceUrl are both the created zaak's URL. /// public sealed record Notification( string Kanaal, string Resource, string Actie, Uri ResourceUrl, Uri? HoofdObject = null) { /// A zaak being created — projected as INGEDIEND. public bool IsZaakCreated => Kanaal == "zaken" && Resource == "zaak" && Actie == "create"; /// A status being set on a zaak — the approval, projected as INGESCHREVEN (S-09b). In the /// walking skeleton the only status ever set after creation is the approval, and the subscriber may /// not read OpenZaak (§8.1), so any status-create is taken as the approval. public bool IsZaakStatusSet => Kanaal == "zaken" && Resource == "status" && Actie == "create"; /// The zaak URL this notification concerns — hoofdObject (the zaak) for a status /// notification, else the resource URL (which, for a zaak-create, is the zaak). public Uri ZaakUrl => HoofdObject ?? ResourceUrl; /// The zaak UUID used as the projection key — the trailing segment of . public string ZaakId => ZaakUrl.Segments[^1].Trim('/'); /// /// A deterministic dedup key. Open Notificaties carries no notification id and may /// redeliver, so the key is derived from the immutable notification content: two /// deliveries of the same zaak-create collapse to one. (NRC may also deliver /// out of order; the projector tolerates that — order does not change the outcome.) /// public string IdempotencyKey => $"{Kanaal}:{Resource}:{Actie}:{ResourceUrl}"; }