Two work packages in one commit because both edit Program.cs and splitting
them would leave a commit that does not build.
WP-72 — deletes POST /api/v1/intakes and /herregistraties. Both were dead
from the UI (the wizard submits via /applications/{id}/submit) and strictly
less capable: they minted a bare reference and wrote no Aanvraag, made no
ZGW call, and did no document-ownership check. The shared Submit(...) helper
survives — /registrations and /change-requests still use it. WP-69 hardened
/intakes with a 400 last session; removing the surface is the stronger fix,
and WP-69's /applications/{id}/submit enforcement is untouched.
WP-73 — RegistrationStatus becomes an abstract record with three sealed
variants behind a private base ctor, so only Geregistreerd carries a
herregistratie deadline and reden is required on Geschorst/Doorgehaald
(matching the FE union, which was already right). HerregistratieRule
.IsStatusConsistent and its test are deleted: the type now guarantees what
the runtime check was for, and the test could no longer construct the
illegal state it existed to catch.
Aanvraag splits into a Concept | Submitted | Decided union with the EF row
demoted to AanvraagEntity behind a two-way mapper. Submitted carries a
non-null Referentie and SubmittedAt, and Decided.Afgewezen/MeerInfoGevraagd
require a Toelichting — so the five Referentie! null-forgiving derefs in
StatusAt are gone, not merely suppressed. IZaakSource.CreateZaak narrows to
Aanvraag.Submitted, removing the same class of deref in both zaak sources.
Draft is now cleared on submit rather than lingering: ApplicationStore's
doc-comment claimed "Concept only" but Submit never cleared it. Verified
nothing reads a submitted aanvraag's draft (draft-sync's applyResume only
resumes unsubmitted wizards), so the comment is now true instead of
aspirational.
No migration, no schema change, no wire change — RegistrationStatusDto and
the application DTOs are byte-identical, confirmed against a live swagger.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
80 lines
4.1 KiB
C#
80 lines
4.1 KiB
C#
using System.Text.Json;
|
|
using BigRegister.Api.Data;
|
|
using BigRegister.Domain.Applications;
|
|
using BigRegister.Domain.Diplomas;
|
|
using BigRegister.Domain.Documents;
|
|
using BigRegister.Domain.People;
|
|
using BigRegister.Domain.Registrations;
|
|
|
|
namespace BigRegister.Api.Contracts;
|
|
|
|
/// <summary>Domain → wire DTO mapping (the anti-corruption boundary, server side).</summary>
|
|
public static class Mappers
|
|
{
|
|
private static string D(DateOnly d) => d.ToString("yyyy-MM-dd");
|
|
|
|
public static RegistrationStatusDto ToDto(this RegistrationStatus s) => s switch
|
|
{
|
|
RegistrationStatus.Geregistreerd g => new(s.Tag.ToString(), HerregistratieDatum: D(g.HerregistratieDatum)),
|
|
RegistrationStatus.Geschorst g => new(s.Tag.ToString(), GeschorstTot: D(g.GeschorstTot), Reden: g.Reden),
|
|
RegistrationStatus.Doorgehaald d => new(s.Tag.ToString(), DoorgehaaldOp: D(d.DoorgehaaldOp), Reden: d.Reden),
|
|
_ => throw new ArgumentOutOfRangeException(nameof(s), s, "Unknown RegistrationStatus variant"),
|
|
};
|
|
|
|
public static RegistrationDto ToDto(this Registration r) => new(
|
|
r.BigNummer, r.Naam, r.Beroep, D(r.Registratiedatum), D(r.Geboortedatum), r.Status.ToDto());
|
|
|
|
public static AdresDto ToDto(this Adres a) => new(a.Straat, a.Postcode, a.Woonplaats);
|
|
|
|
public static PersonDto ToDto(this Person p) => new(p.Naam, D(p.Geboortedatum), p.Adres.ToDto());
|
|
|
|
public static PolicyQuestionDto ToDto(this PolicyQuestion q) => new(
|
|
q.Id, q.Vraag, q.Type == QuestionType.JaNee ? "ja-nee" : "tekst");
|
|
|
|
public static DuoDiplomaDto ToDto(this Diploma d) => new(
|
|
d.Id, d.Naam, d.Instelling, d.Jaar,
|
|
DiplomaRules.ProfessionFor(d),
|
|
DiplomaRules.QuestionsFor(d).Select(q => q.ToDto()).ToList());
|
|
|
|
public static DocumentCategoryDto ToDto(this DocumentCategory c) => new(
|
|
c.CategoryId, c.Label, c.Description, c.Required, c.AcceptedTypes, c.MaxSizeMb, c.Multiple, c.AllowPostDelivery);
|
|
|
|
/// <summary>Wire projection of an <see cref="AanvraagStatus"/> — the null "Concept" case
|
|
/// is the one place a status has no <see cref="AanvraagStatusTag"/>, so it becomes the wire
|
|
/// convention's magic string here at the boundary rather than living inside the domain type.
|
|
/// Shared by <see cref="ToStatusDto"/> and <c>ZgwZaakMapper</c>, so both status producers
|
|
/// agree on the projection (WP-68 F3).</summary>
|
|
public static AanvraagStatusDto ToDto(this AanvraagStatus s) => new(
|
|
s.Tag?.ToString() ?? "Concept", s.StepIndex, s.StepCount, s.Referentie, s.Manual, s.Reden);
|
|
|
|
// Aanvraag status is COMPUTED ON READ (see the StatusAt extension, Data/AanvraagMapper.cs) —
|
|
// this is now a one-line projection of that onto the wire DTO (WP-68 F3, WP-73).
|
|
public static AanvraagStatusDto ToStatusDto(this Aanvraag a, DateTimeOffset now) => a.StatusAt(now).ToDto();
|
|
|
|
/// <summary>SubmittedAt only exists once Submitted/Decided (WP-73) — null for a Concept,
|
|
/// same as the wire DTO's own nullable field.</summary>
|
|
private static string? SubmittedAtOf(Aanvraag a) => a switch
|
|
{
|
|
Aanvraag.Concept => null,
|
|
Aanvraag.Submitted s => s.SubmittedAt.ToString("o"),
|
|
Aanvraag.Decided d => d.SubmittedAt.ToString("o"),
|
|
_ => null,
|
|
};
|
|
|
|
/// <summary>Draft only exists pre-submission (WP-73) — null once Submitted/Decided (nothing
|
|
/// reads it past that point; see <c>AanvraagMapper.ApplyTo</c>'s Submitted branch).</summary>
|
|
private static JsonElement? DraftOf(Aanvraag a) => a is Aanvraag.Concept c ? c.Draft : null;
|
|
|
|
public static ApplicationSummaryDto ToSummaryDto(this Aanvraag a, DateTimeOffset now) => new(
|
|
a.Id, a.Type, a.ToStatusDto(now), a.DocumentIds,
|
|
a.CreatedAt.ToString("o"), a.UpdatedAt.ToString("o"), SubmittedAtOf(a));
|
|
|
|
/// Admin summary — same shape plus the owner (WP-36; the user-facing list leaves Owner null).
|
|
public static ApplicationSummaryDto ToAdminSummaryDto(this Aanvraag a, DateTimeOffset now) =>
|
|
a.ToSummaryDto(now) with { Owner = a.Owner };
|
|
|
|
public static ApplicationDetailDto ToDetailDto(this Aanvraag a, DateTimeOffset now) => new(
|
|
a.Id, a.Type, a.ToStatusDto(now), DraftOf(a), a.DocumentIds,
|
|
a.CreatedAt.ToString("o"), a.UpdatedAt.ToString("o"), SubmittedAtOf(a));
|
|
}
|