feat(acl): CancelZaakAsync service + POST /annuleringen endpoint (S-10c) (refs #106)
The ACL exposes zaak cancellation as a service operation the domain calls on document-timeout expiry; it default-fills the zaaktype and dates the status today, translating the domain intent to the ZGW cancellation status/resultaat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,14 @@ app.MapPost("/statussen", async (SetStatusRequest body, AclService acl, Cancella
|
||||
return Results.NoContent();
|
||||
});
|
||||
|
||||
// Cancel a zaak on document-timeout expiry (S-10c): set it to its zaaktype's cancellation statustype
|
||||
// + resultaat. The domain hands over only the zaak URL; the ACL owns the ZGW resolution (§8.1).
|
||||
app.MapPost("/annuleringen", async (CancelZaakRequest body, AclService acl, CancellationToken ct) =>
|
||||
{
|
||||
await acl.CancelZaakAsync(new Uri(body.ZaakUrl), ct);
|
||||
return Results.NoContent();
|
||||
});
|
||||
|
||||
// Read a zaak's public-safe reference (its identificatie). The Event Subscriber calls this to enrich
|
||||
// the read projection without reading ZGW itself (§8.1, #78).
|
||||
app.MapPost("/zaken/reference", async (ZaakReferenceRequest body, AclService acl, CancellationToken ct) =>
|
||||
@@ -55,6 +63,8 @@ public sealed record OpenZaakRequest(string Bsn, string Reference);
|
||||
|
||||
public sealed record SetStatusRequest(string ZaakUrl);
|
||||
|
||||
public sealed record CancelZaakRequest(string ZaakUrl);
|
||||
|
||||
public sealed record ZaakReferenceRequest(string ZaakUrl);
|
||||
|
||||
public sealed record StoreDocumentRequest(string ZaakUrl, string ContentBase64, string FileName, string ContentType);
|
||||
|
||||
@@ -30,6 +30,18 @@ public sealed class AclService(IZaakGateway gateway, AclDefaults defaults, ICloc
|
||||
return gateway.SetZaakToEindstatusAsync(zaakUrl, defaults.ZaaktypeUrl, clock.Today, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancel a zaak on document-timeout expiry (S-10c): set it to the configured BIG zaaktype's
|
||||
/// cancellation statustype + resultaat. The domain hands over only the zaak URL; the ACL owns which
|
||||
/// statustype/resultaat means "cancelled" (§8.1).
|
||||
/// </summary>
|
||||
public Task CancelZaakAsync(Uri zaakUrl, CancellationToken ct = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(zaakUrl);
|
||||
|
||||
return gateway.SetZaakToCancellationStatusAsync(zaakUrl, defaults.ZaaktypeUrl, clock.Today, ct);
|
||||
}
|
||||
|
||||
/// <summary>The zaak's reference (its ZGW identificatie), for the read projection (#78).</summary>
|
||||
public Task<string> GetZaakReferenceAsync(Uri zaakUrl, CancellationToken ct = default)
|
||||
{
|
||||
|
||||
@@ -134,6 +134,34 @@ public class AclServiceTests
|
||||
Assert.Null(gateway.Approved);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Cancelling_a_zaak_sets_it_to_the_cancellation_status_dated_today()
|
||||
{
|
||||
var gateway = new FakeGateway();
|
||||
var defaults = Defaults();
|
||||
var service = new AclService(gateway, defaults, new FixedClock(new DateOnly(2026, 6, 4)));
|
||||
var zaak = new Uri("http://openzaak/zaken/api/v1/zaken/abc");
|
||||
|
||||
await service.CancelZaakAsync(zaak);
|
||||
|
||||
Assert.NotNull(gateway.Cancelled);
|
||||
Assert.Equal(zaak, gateway.Cancelled!.Value.Zaak);
|
||||
Assert.Equal(defaults.ZaaktypeUrl, gateway.Cancelled.Value.Zaaktype);
|
||||
Assert.Equal(new DateOnly(2026, 6, 4), gateway.Cancelled.Value.Datum);
|
||||
// Cancellation must not touch the approval path.
|
||||
Assert.Null(gateway.Approved);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Cancelling_a_null_zaak_is_rejected_without_touching_the_gateway()
|
||||
{
|
||||
var gateway = new FakeGateway();
|
||||
var service = new AclService(gateway, Defaults(), new FixedClock(new DateOnly(2026, 6, 4)));
|
||||
|
||||
await Assert.ThrowsAsync<ArgumentNullException>(() => service.CancelZaakAsync(null!));
|
||||
Assert.Null(gateway.Cancelled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Storing_a_diploma_default_fills_the_document_fields_and_returns_its_url()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user