diff --git a/register-referentie.slnx b/register-referentie.slnx index 3a5661a..40d5e27 100644 --- a/register-referentie.slnx +++ b/register-referentie.slnx @@ -7,6 +7,10 @@ + + + + diff --git a/services/domain/Big.Domain/Big.Domain.csproj b/services/domain/Big.Domain/Big.Domain.csproj new file mode 100644 index 0000000..7fe1710 --- /dev/null +++ b/services/domain/Big.Domain/Big.Domain.csproj @@ -0,0 +1,11 @@ + + + + + net10.0 + enable + enable + + + diff --git a/services/domain/Big.Domain/Registration.cs b/services/domain/Big.Domain/Registration.cs new file mode 100644 index 0000000..591d15e --- /dev/null +++ b/services/domain/Big.Domain/Registration.cs @@ -0,0 +1,47 @@ +namespace Big.Domain; + +/// +/// The Registration aggregate root (CLAUDE.md §2.2): a zorgprofessional's submission to the BIG +/// register. It owns its lifecycle invariants — it starts +/// on submission, remembers the Flowable process that drives it, and records the zaak the ACL opens. +/// +public sealed class Registration +{ + // STUB (red): mutators are no-ops and Submit leaves the bsn empty so the behaviour tests + // compile and fail on their assertions. The green commit implements the invariants. + private Registration(RegistrationId id, string bsn) + { + Id = id; + Bsn = bsn; + Status = RegistrationStatus.Ingediend; + } + + public RegistrationId Id { get; } + + /// The citizen-service number of the submitting zorgprofessional. Handed to the ACL + /// as the domain payload; the domain never constructs ZGW concepts from it (§8.1). + public string Bsn { get; } + + public RegistrationStatus Status { get; private set; } + + /// The Flowable process instance driving this registration, once started. + public string? ProcessInstanceId { get; private set; } + + /// The zaak the ACL opened for this registration, once the external task has run. + public Uri? ZaakUrl { get; private set; } + + /// Submit a new registration. It begins in . + public static Registration Submit(string bsn) => new(RegistrationId.New(), string.Empty); + + /// Record that the registratie workflow process has been started for this registration. + public void RecordProcessStarted(string processInstanceId) + { + // STUB (red). + } + + /// Attach the zaak the ACL opened. Idempotent on the same URL; a conflicting URL is rejected. + public void AttachZaak(Uri zaakUrl) + { + // STUB (red). + } +} diff --git a/services/domain/Big.Domain/RegistrationId.cs b/services/domain/Big.Domain/RegistrationId.cs new file mode 100644 index 0000000..e9c8505 --- /dev/null +++ b/services/domain/Big.Domain/RegistrationId.cs @@ -0,0 +1,15 @@ +namespace Big.Domain; + +/// The identity of a aggregate — opaque, server-assigned, +/// and distinct from the OpenZaak zaak id (which the projection keys on). A value object so the +/// id can travel as a Flowable process variable and back without ever being a bare string. +public readonly record struct RegistrationId(Guid Value) +{ + /// Mint a fresh identity for a newly submitted registration. + public static RegistrationId New() => new(Guid.NewGuid()); + + /// Rehydrate an id carried as a string (e.g. a Flowable process variable). + public static RegistrationId Parse(string value) => new(Guid.Parse(value)); + + public override string ToString() => Value.ToString(); +} diff --git a/services/domain/Big.Domain/RegistrationStatus.cs b/services/domain/Big.Domain/RegistrationStatus.cs new file mode 100644 index 0000000..3ddad57 --- /dev/null +++ b/services/domain/Big.Domain/RegistrationStatus.cs @@ -0,0 +1,10 @@ +namespace Big.Domain; + +/// The lifecycle states a moves through. The walking +/// skeleton knows only ; withdrawal, beoordeling and herregistratie +/// states arrive in their own slices (Iteration 2+). +public enum RegistrationStatus +{ + /// Submitted by the zorgprofessional; the registratie process has been started. + Ingediend, +} diff --git a/services/domain/Big.Tests/Big.Tests.csproj b/services/domain/Big.Tests/Big.Tests.csproj new file mode 100644 index 0000000..575ce15 --- /dev/null +++ b/services/domain/Big.Tests/Big.Tests.csproj @@ -0,0 +1,25 @@ + + + + net10.0 + enable + enable + false + + + + + + + + + + + + + + + + + + diff --git a/services/domain/Big.Tests/RegistrationTests.cs b/services/domain/Big.Tests/RegistrationTests.cs new file mode 100644 index 0000000..43b57f6 --- /dev/null +++ b/services/domain/Big.Tests/RegistrationTests.cs @@ -0,0 +1,77 @@ +using Big.Domain; + +namespace Big.Tests; + +public class RegistrationTests +{ + [Fact] + public void Submitting_a_registration_starts_in_ingediend() + { + var registration = Registration.Submit("123456782"); + + Assert.Equal(RegistrationStatus.Ingediend, registration.Status); + Assert.Equal("123456782", registration.Bsn); + Assert.NotEqual(Guid.Empty, registration.Id.Value); + Assert.Null(registration.ZaakUrl); + Assert.Null(registration.ProcessInstanceId); + } + + [Theory] + [InlineData("")] + [InlineData(" ")] + [InlineData(null)] + public void Submitting_without_a_bsn_is_rejected(string? bsn) + => Assert.Throws(() => Registration.Submit(bsn!)); + + [Fact] + public void Recording_the_started_process_keeps_its_instance_id() + { + var registration = Registration.Submit("123456782"); + + registration.RecordProcessStarted("proc-42"); + + Assert.Equal("proc-42", registration.ProcessInstanceId); + } + + [Fact] + public void Attaching_a_zaak_records_its_url_and_keeps_the_status_ingediend() + { + var registration = Registration.Submit("123456782"); + var zaak = new Uri("http://openzaak/zaken/api/v1/zaken/abc"); + + registration.AttachZaak(zaak); + + Assert.Equal(zaak, registration.ZaakUrl); + Assert.Equal(RegistrationStatus.Ingediend, registration.Status); + } + + [Fact] + public void Attaching_a_null_zaak_is_rejected() + { + var registration = Registration.Submit("123456782"); + + Assert.Throws(() => registration.AttachZaak(null!)); + } + + [Fact] + public void Re_attaching_the_same_zaak_is_idempotent() + { + var registration = Registration.Submit("123456782"); + var zaak = new Uri("http://openzaak/zaken/api/v1/zaken/abc"); + + registration.AttachZaak(zaak); + registration.AttachZaak(zaak); + + Assert.Equal(zaak, registration.ZaakUrl); + } + + [Fact] + public void Attaching_a_conflicting_zaak_is_rejected() + { + var registration = Registration.Submit("123456782"); + registration.AttachZaak(new Uri("http://openzaak/zaken/api/v1/zaken/abc")); + + Assert.Throws( + () => registration.AttachZaak(new Uri("http://openzaak/zaken/api/v1/zaken/other"))); + } +} diff --git a/services/domain/Big.slnx b/services/domain/Big.slnx new file mode 100644 index 0000000..6125bff --- /dev/null +++ b/services/domain/Big.slnx @@ -0,0 +1,4 @@ + + + +