using Big.Application; using Big.Domain; namespace Big.Tests; /// /// 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. Either way the decision also completes the Flowable Beoordelen task (found by /// registrationId) so the process advances. All idempotent — a repeated decision is a no-op. /// public class BeoordeelRegistratieTests { private static Registration WithZaak(string bsn = "123456782") { var registration = Registration.Submit(bsn); registration.AttachZaak(FakeAclClient.DefaultZaakUrl); return registration; } private static FakeUserTaskClient TaskFor(Registration registration) => new([new BeoordelingTask("task-1", registration.Id)]); [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 tasks = TaskFor(registration); var handler = new BeoordeelRegistratie(store, acl, tasks); 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); // The behandelaar's decision advances the workflow: the Beoordelen task is completed. Assert.Equal(("task-1", BeoordelingsBesluit.Goedkeuren), tasks.Completed); } [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 tasks = TaskFor(registration); var handler = new BeoordeelRegistratie(store, acl, tasks); 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); Assert.Equal(("task-1", BeoordelingsBesluit.Afwijzen), tasks.Completed); } [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, TaskFor(registration)); 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, new FakeUserTaskClient([])); await Assert.ThrowsAsync(() => 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, new FakeUserTaskClient([])); var ex = await Assert.ThrowsAsync(() => 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, TaskFor(registration)); var ex = await Assert.ThrowsAsync(() => 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, TaskFor(registration)); 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, TaskFor(registration)); 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); } [Fact] public async Task Deciding_completes_no_task_when_none_is_open_for_the_registration() { // The task may already be gone (redelivery / manual completion). The decision still applies // and simply completes nothing rather than failing. var store = new FakeRegistrationStore(); var acl = new FakeAclClient(); var registration = WithZaak(); store.Seed(registration); var tasks = new FakeUserTaskClient([]); // no open task for this registration var handler = new BeoordeelRegistratie(store, acl, tasks); await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren)); Assert.Equal(RegistrationStatus.Ingeschreven, (await store.GetAsync(registration.Id))!.Status); Assert.Null(tasks.Completed); } }