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 UUID used as the projection key. For a status notification the resource URL is /// the status, so the zaak comes from hoofdObject (which, for a zaak-create, equals the /// resource URL) — see the NRC payload note. public string ZaakId => (HoofdObject ?? ResourceUrl).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}"; }