feat(zgw): OpenZaak Documenten (DRC) upload + zaak link (WP-51)

Extends the OpenZaak seam with IDocumentSource, sibling of IZaakSource
(WP-49/50): an upload always lands locally first (DocumentStore stays
the record of truth for preview/download/audit) and, when
Zgw:Enabled=true, is also registered as a DRC enkelvoudiginformatie-
object; once a zaak exists (IZaakSource.CreateZaak now also returns
its ZaakUrl), submit links each document to it via zaakinformatie-
object. FE upload/list DTOs are unchanged.

- ZgwOptions gains DrcBaseUrl + a category->informatieobjecttype URL
  map (the document analogue of ZaaktypeUrls).
- LocalDocumentSource is the same DocumentStore.Add/Link calls the
  endpoints used to make inline — zero behaviour change offline.
- OpenZaakDocumentSource POSTs the eio then the zaak link, persisting
  the DRC url (DocumentStore.SetDrcUrl) so linking doesn't re-upload.
- Factored the GET/POST-with-bearer-JWT plumbing shared with
  OpenZaakZaakSource into ZgwHttpClient; shared the stub handler
  between the two source test classes as ZgwStubHandler.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-07-29 20:54:31 +02:00
co-authored by Claude Sonnet 5
parent 3671684528
commit 5807937229
18 changed files with 836 additions and 116 deletions
@@ -26,6 +26,13 @@ public sealed class Aanvraag
public DateTimeOffset CreatedAt { get; init; }
public DateTimeOffset UpdatedAt { get; set; }
public DateTimeOffset? SubmittedAt { get; set; }
/// <summary>The OpenZaak zaak's URL, set once CreateZaak (WP-50) registers one — null under
/// the local source. Persisted so later steps (WP-51's document→zaak link) can find it
/// without a network round-trip; IZaakSource.CreateZaak itself doesn't write here (the
/// endpoint does, via <see cref="ApplicationStore.SetZaakUrl"/>) to keep the seam's write
/// surface at "return data", not "reach into another store".</summary>
public string? ZaakUrl { get; set; }
}
/// <summary>
@@ -172,4 +179,18 @@ public static class ApplicationStore
return a;
}
}
/// <summary>Persist the zaak URL CreateZaak (WP-50) registered for this aanvraag. No-op if
/// the aanvraag is gone (shouldn't happen — this runs right after Submit found it).</summary>
public static void SetZaakUrl(string id, string zaakUrl)
{
lock (_gate)
{
using var db = Db.Create();
var a = db.Applications.Find(id);
if (a is null) return;
a.ZaakUrl = zaakUrl;
db.SaveChanges();
}
}
}