feat(behandelportal): WP-66 wire the decision into OpenZaak

Extends IZaakSource with RecordBesluit, mirroring WP-50's CreateZaak write
pattern: OpenZaakZaakSource POSTs a new Statussen entry (highest-volgnummer
statustype, since the harness catalogus has no per-outcome besluittype),
carrying the besluit + toelichting in statustoelichting; LocalZaakSource
no-ops. The beoordeling endpoint calls it after the local decision commits,
flagging a failure via RecordZgwDivergence the same way submit's
create-zaak/document writes do — closing WP-60's "second write pair" gap.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-08-04 09:41:28 +02:00
co-authored by Claude Sonnet 5
parent 39409bdf76
commit d996ca2463
8 changed files with 203 additions and 22 deletions
+20 -6
View File
@@ -442,13 +442,14 @@ api.MapGet("/beoordeling/{id}", (string id, HttpContext ctx, IZaakSource zaken)
.ProducesProblem(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
// --- Besluit (WP-65b): record a behandelaar's decision, advancing the WP-63 status
// lifecycle. Runs against ApplicationStore directly (not the IZaakSource seam) — same
// reasoning as the GET above: a new seam method would force an OpenZaakZaakSource
// write now, which is WP-66's surface, not this one's. The transition-legality check
// --- Besluit (WP-65b/66): record a behandelaar's decision, advancing the WP-63 status
// lifecycle. The local write runs against ApplicationStore directly (not the IZaakSource
// seam) — same reasoning as the GET above. The transition-legality check
// (BeoordelingRules.CanDecide) is the SAME function the GET's canBesluiten flag uses,
// so the two can never drift.
api.MapPost("/beoordeling/{id}/besluit", (string id, RecordBesluitRequest req, HttpContext ctx) =>
// so the two can never drift. WP-66: once the local decision has committed, IZaakSource
// also gets a chance to advance the ZGW-side zaak status — LocalZaakSource no-ops,
// OpenZaakZaakSource POSTs a new Statussen entry (see its RecordBesluit).
api.MapPost("/beoordeling/{id}/besluit", (string id, RecordBesluitRequest req, HttpContext ctx, IZaakSource zaken) =>
Beoordelen(ctx, $"aanvraag/{id}/besluit", () =>
{
if (!Enum.TryParse<Besluit>(req.Besluit, out var besluit))
@@ -468,6 +469,19 @@ api.MapPost("/beoordeling/{id}/besluit", (string id, RecordBesluitRequest req, H
var updated = ApplicationStore.RecordBesluit(id, besluit, req.Toelichting)!;
app.Logger.LogInformation("aanvraag besluit id={Id} besluit={Besluit}", id, besluit);
// WP-60: the local decision above already committed — a ZGW failure here is caught and
// flagged rather than allowed to diverge silently, same handling as submit's create-zaak
// and document-link writes.
try
{
zaken.RecordBesluit(updated, besluit, req.Toelichting, now, ctx.Caller());
}
catch (Exception ex)
{
RecordZgwDivergence(ctx, id, updated.Referentie ?? id, ex);
}
return Results.Ok(new RecordBesluitResponse(updated.ToStatusDto(now)));
}))
.Produces<RecordBesluitResponse>()