feat(#13): S-12a — beoordeling decision model (domain) #82

Open
not wants to merge 7 commits from feat/13-behandel-decision-model into main
Showing only changes of commit 63699c3f55 - Show all commits

View File

@@ -0,0 +1,142 @@
using Big.Application;
using Big.Domain;
namespace Big.Tests;
/// <summary>
/// The beoordeling use case (S-12): a behandelaar's decision on a registration. Goedkeuren sets the
/// zaak's final status via the ACL (§8.1) and marks the aggregate INGESCHREVEN; Afwijzen marks it
/// AFGEWEZEN in the domain (propagating a rejection to the zaak is a later sub-slice). Both are
/// idempotent so a repeated or redelivered decision is a no-op.
/// </summary>
public class BeoordeelRegistratieTests
{
private static Registration WithZaak(string bsn = "123456782")
{
var registration = Registration.Submit(bsn);
registration.AttachZaak(FakeAclClient.DefaultZaakUrl);
return registration;
}
[Fact]
public async Task Goedkeuren_sets_the_zaak_status_via_the_acl_and_marks_the_registration_ingeschreven()
{
var store = new FakeRegistrationStore();
var acl = new FakeAclClient();
var registration = WithZaak();
store.Seed(registration);
var handler = new BeoordeelRegistratie(store, acl);
await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren));
var saved = await store.GetAsync(registration.Id);
Assert.Equal(RegistrationStatus.Ingeschreven, saved!.Status);
Assert.Equal(FakeAclClient.DefaultZaakUrl, acl.ApprovedZaakUrl);
Assert.Equal(1, acl.ApproveCallCount);
Assert.Equal(1, store.SaveCount);
}
[Fact]
public async Task Afwijzen_marks_the_registration_afgewezen_without_calling_the_acl()
{
var store = new FakeRegistrationStore();
var acl = new FakeAclClient();
var registration = WithZaak();
store.Seed(registration);
var handler = new BeoordeelRegistratie(store, acl);
await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Afwijzen));
var saved = await store.GetAsync(registration.Id);
Assert.Equal(RegistrationStatus.Afgewezen, saved!.Status);
Assert.Equal(0, acl.ApproveCallCount);
Assert.Equal(1, store.SaveCount);
}
[Fact]
public async Task Goedkeuren_an_in_behandeling_registration_marks_it_ingeschreven()
{
var store = new FakeRegistrationStore();
var acl = new FakeAclClient();
var registration = WithZaak();
registration.TakeIntoBehandeling();
store.Seed(registration);
var handler = new BeoordeelRegistratie(store, acl);
await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren));
Assert.Equal(RegistrationStatus.Ingeschreven, (await store.GetAsync(registration.Id))!.Status);
}
[Fact]
public async Task Rejects_a_null_command_without_touching_the_store_or_acl()
{
var store = new FakeRegistrationStore();
var acl = new FakeAclClient();
var handler = new BeoordeelRegistratie(store, acl);
await Assert.ThrowsAsync<ArgumentNullException>(() => handler.HandleAsync(null!));
Assert.Equal(0, acl.ApproveCallCount);
Assert.Equal(0, store.SaveCount);
}
[Fact]
public async Task Deciding_an_unknown_registration_throws_and_does_not_call_the_acl()
{
var store = new FakeRegistrationStore();
var acl = new FakeAclClient();
var handler = new BeoordeelRegistratie(store, acl);
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() =>
handler.HandleAsync(new BeoordeelRegistratieCommand(RegistrationId.New(), BeoordelingsBesluit.Goedkeuren)));
Assert.Contains("No registration", ex.Message);
Assert.Equal(0, acl.ApproveCallCount);
}
[Fact]
public async Task Goedkeuren_before_the_zaak_is_opened_throws_without_calling_the_acl()
{
var store = new FakeRegistrationStore();
var acl = new FakeAclClient();
var registration = Registration.Submit("123456782"); // no zaak yet
store.Seed(registration);
var handler = new BeoordeelRegistratie(store, acl);
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() =>
handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren)));
Assert.Contains("no zaak", ex.Message);
Assert.Equal(0, acl.ApproveCallCount);
}
[Fact]
public async Task Re_goedkeuren_an_already_ingeschreven_registration_is_idempotent()
{
var store = new FakeRegistrationStore();
var acl = new FakeAclClient();
var registration = WithZaak();
store.Seed(registration);
var handler = new BeoordeelRegistratie(store, acl);
await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren));
await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren));
Assert.Equal(1, acl.ApproveCallCount);
Assert.Equal(RegistrationStatus.Ingeschreven, (await store.GetAsync(registration.Id))!.Status);
}
[Fact]
public async Task Re_afwijzen_an_already_afgewezen_registration_is_idempotent()
{
var store = new FakeRegistrationStore();
var acl = new FakeAclClient();
var registration = WithZaak();
store.Seed(registration);
var handler = new BeoordeelRegistratie(store, acl);
await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Afwijzen));
await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Afwijzen));
Assert.Equal(1, store.SaveCount);
Assert.Equal(RegistrationStatus.Afgewezen, (await store.GetAsync(registration.Id))!.Status);
}
}