Files
atomic-design-poc/backend/src/BigRegister.Api/Zgw/ZgwZaakMapper.cs
T
ehoandClaude Opus 4.8 1c3c195d32
CI / frontend (push) Successful in 2m59s
CI / backend (push) Successful in 1m27s
CI / semgrep (push) Successful in 58s
CI / e2e (push) Successful in 2m30s
CI / api-client-drift (push) Canceled after 1m14s
CI / storybook-a11y (push) Canceled after 29m8s
feat(backend): expand stamdata + OpenZaak-ready cases seam (WP-49)
Stamdata: add beroepen, opleidingen (temporal), and specialismen tables to the
schema-driven catalog (zero UI code). opleidingen.beroep and specialismen.beroep
both reference beroepen.code — the first stamdata->stamdata references, enforced by
two new StamdataRef entries in the CI gate.

OpenZaak/ZGW (WP-49, slice 1 — read-only zaken): introduce IZaakSource as the cases
read seam. Default LocalZaakSource reads the local SQLite store (offline); an
OpenZaakZaakSource (Zgw/ client: HS256 per-call JWT, ZGW->existing-DTO mapper,
paginating HTTP source) is selected behind Zgw:Enabled (default false). The FE never
changes — same ApplicationSummaryDto, no api-client drift. Unit-tested with fixtures
+ a stub HttpMessageHandler; no live OpenZaak needed.

Docs: ADR-0005, reference/openzaak-integration.md, WP-49..52 roadmap, stamdata.md
update, README index rows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 15:01:06 +02:00

59 lines
2.9 KiB
C#

using System.Text.Json.Serialization;
using BigRegister.Api.Contracts;
namespace BigRegister.Api.Zgw;
/// <summary>
/// The subset of a ZGW Zaak (Zaken API / ZRC) the read slice needs. The full resource has
/// dozens of fields; we bind only what maps to <see cref="ApplicationSummaryDto"/>. Note the
/// two ZGW traits that force an anti-corruption layer: <see cref="Url"/> is the resource's
/// identity (not a bare id), and <see cref="Zaaktype"/> is a URL <em>into another service</em>
/// (Catalogi/ZTC) that must be resolved to a human label.
/// </summary>
public sealed record ZgwZaak(
[property: JsonPropertyName("url")] string Url,
[property: JsonPropertyName("identificatie")] string Identificatie,
[property: JsonPropertyName("zaaktype")] string Zaaktype,
[property: JsonPropertyName("startdatum")] DateOnly Startdatum,
[property: JsonPropertyName("einddatum")] DateOnly? Einddatum,
[property: JsonPropertyName("registratiedatum")] DateOnly? Registratiedatum);
/// <summary>
/// Anti-corruption map: ZGW Zaak → the existing <see cref="ApplicationSummaryDto"/> the FE
/// already renders (WP-49). This is where "URL as identity" and the cross-service zaaktype
/// join get flattened away, so nothing downstream (the FE) sees ZGW shapes.
/// </summary>
public static class ZgwZaakMapper
{
/// <summary>Last path segment of a ZGW resource URL — the uuid that identifies it.</summary>
public static string Uuid(string url) => url.TrimEnd('/').Split('/').Last();
public static ApplicationSummaryDto ToSummaryDto(ZgwZaak z, string zaaktypeLabel)
{
// ponytail: coarse status map — an open zaak (no einddatum) is In behandeling, a closed
// one is Goedgekeurd. Real fidelity (statustype/resultaat lookups) is a later slice; the
// Afgewezen path needs the resultaat resource. Enough to prove the seam end-to-end.
var status = z.Einddatum is null
? new AanvraagStatusDto("InBehandeling", Referentie: z.Identificatie, Manual: true)
: new AanvraagStatusDto("Goedgekeurd", Referentie: z.Identificatie);
var created = Iso(z.Registratiedatum ?? z.Startdatum);
var updated = Iso(z.Einddatum ?? z.Registratiedatum ?? z.Startdatum);
return new ApplicationSummaryDto(
Id: Uuid(z.Url),
Type: zaaktypeLabel,
Status: status,
DocumentIds: Array.Empty<string>(), // zaak↔document links arrive with WP-51 (DRC)
CreatedAt: created,
UpdatedAt: updated,
SubmittedAt: created,
Owner: z.Identificatie); // real initiator (rol/BSN) needs a rollen lookup — later slice
}
// Keep the wire shape identical to the local source (round-trip datetime): a ZGW date
// becomes midnight UTC so the FE's date parsing sees the same format either backend.
private static string Iso(DateOnly d) =>
d.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc).ToString("o");
}