feat(#13): S-12c-2 — behandel decide → domain + complete workflow task (#86)
All checks were successful
CI / lint (push) Successful in 1m17s
CI / build (push) Successful in 1m0s
CI / unit (push) Successful in 1m8s
CI / frontend (push) Successful in 2m20s
CI / mutation (push) Successful in 4m57s
CI / verify-stack (push) Successful in 7m3s

## What & why

Second half of **S-12c** (behandel-portal backend), completing the decision path per **ADR-0013**:

- **Domain:** `BeoordeelRegistratie` now, after applying the decision (aggregate + ACL for approval), **completes the open Flowable `Beoordelen` task** for that registration (found by registrationId) with the besluit, so the workflow advances. No open task → the decision still stands (completes nothing); idempotent.
- **BFF:** `POST /behandel/registrations/{id}/decide` behind the medewerker/`behandelaar` policy, forwarding `goedkeuren`/`afwijzen` to the domain. Validates the besluit vocabulary (400 on unknown) without troubling the domain.

Behavior: decide is **401** without a token, **403** without the role, **400** for an unknown besluit, **204** (forwarded) for a behandelaar.

This completes the behandel backend. **S-12d** (the Angular behandel-portal + Playwright e2e) closes umbrella #13 and retires the temporary `/approve`.

## Definition of Done

- [x] Linked issue: #13 (umbrella, `refs`)
- [x] Tests first; red → green per layer
- [x] Unit + acceptance green (`make unit`): domain 79, bff 27, acceptance 9 (acl/event-subscriber unaffected)
- [x] Beoordeling acceptance scenario asserts task completion (goedkeuren + afwijzen)
- [x] openapi.json + api-client regenerated (drift guard passes)
- [x] Mutation ≥ break(90): **domain 100%, bff 100%**
- [ ] CI green (pending)

Part of #13.

Reviewed-on: #86
This commit was merged in pull request #86.
This commit is contained in:
2026-07-16 06:53:52 +00:00
parent 9c3da48d8e
commit d226b6402d
12 changed files with 284 additions and 14 deletions

View File

@@ -16,6 +16,7 @@ public sealed class EenRegistratieBeoordelenSteps
{
private readonly InMemoryAclClient _acl = new();
private readonly InMemoryRegistrationStore _store = new();
private readonly InMemoryUserTaskClient _tasks = new();
private RegistrationId _id;
[Given("a submitted registration with an opened zaak")]
@@ -25,6 +26,8 @@ public sealed class EenRegistratieBeoordelenSteps
registration.AttachZaak(InMemoryAclClient.OpenedZaakUrl);
await _store.SaveAsync(registration);
_id = registration.Id;
// The process has parked at the Beoordelen user task awaiting the behandelaar.
_tasks.Open(_id);
}
[When("the behandelaar takes it into behandeling")]
@@ -37,7 +40,7 @@ public sealed class EenRegistratieBeoordelenSteps
[When("the behandelaar decides \"(.*)\"")]
public async Task WhenTheBehandelaarDecides(string besluit)
=> await new BeoordeelRegistratie(_store, _acl).HandleAsync(
=> await new BeoordeelRegistratie(_store, _acl, _tasks).HandleAsync(
new BeoordeelRegistratieCommand(_id, Enum.Parse<BeoordelingsBesluit>(besluit, ignoreCase: true)));
[Then("the registration has status \"(.*)\"")]
@@ -55,4 +58,8 @@ public sealed class EenRegistratieBeoordelenSteps
[Then("the ACL is not asked to set the zaak status")]
public void ThenTheAclIsNotAskedToSetTheZaakStatus()
=> Assert.Null(_acl.ApprovedZaakUrl);
[Then("the beoordeling task is completed with \"(.*)\"")]
public void ThenTheBeoordelingTaskIsCompletedWith(string besluit)
=> Assert.Equal(Enum.Parse<BeoordelingsBesluit>(besluit, ignoreCase: true), _tasks.Completed?.Besluit);
}