The wire said Application, the domain said Aanvraag — one aggregate with two names at every hop. Rename the backend DTOs and the /applications route to /aanvragen, regenerate the typed client, and rename the frontend adapter/store to match. Renamed: ApplicationSummaryDto/DetailDto, CreateApplicationRequest, SubmitApplicationRequest/Response → Aanvraag* equivalents; ApplicationsAdapter/Store → AanvragenAdapter/Store; applications.adapter.ts/applications.store.ts → aanvragen.*. Left untouched: the admin Case/Zaak vocabulary (/admin/cases, AdminCasesStore) — a separate read model, not part of this rename; the internal BigRegister.Domain.Applications namespace and the Applications EF table (renaming those needs a new EF migration, out of scope here). Part of the dashboard-readability refactor (see the approved plan). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
43 lines
2.3 KiB
C#
43 lines
2.3 KiB
C#
namespace BigRegister.Domain.Intake;
|
|
|
|
/// <summary>
|
|
/// Config value (ADR-0001's "config value" shape). Below this many NL work-hours the
|
|
/// scholing question is required. The frontend receives this value
|
|
/// (<c>GET /intake/policy</c>) and applies it for instant UX feedback
|
|
/// (<c>intake.machine.ts</c>'s <c>lageUren</c>); <see cref="RejectIncompleteScholing"/> is the
|
|
/// backend re-validating it as the authority on submit (WP-69) —
|
|
/// <c>POST /aanvragen/{id}/submit</c> (intake-typed aanvragen only) calls it before
|
|
/// writing anything, and a violation 400s (<c>ProblemDetails</c>), never silently accepts
|
|
/// an incomplete answer.
|
|
/// </summary>
|
|
public static class IntakePolicy
|
|
{
|
|
public const int ScholingThreshold = 1000;
|
|
|
|
/// <summary>
|
|
/// Completeness rule for the scholing question (WP-69) — not merit: below
|
|
/// <see cref="ScholingThreshold"/> an answer must be present, but "nee" is a legal answer
|
|
/// that still submits (turning "few uren + no scholing" into a rejection is out of scope,
|
|
/// see the WP). Three-valued, so two parameters (uren, punten) couldn't express it:
|
|
/// <list type="bullet">
|
|
/// <item>below threshold and no answer at all ⇒ incomplete;</item>
|
|
/// <item>answered <c>true</c> (scholing gevolgd) ⇒ punten required and non-negative
|
|
/// (mirrors <c>parseUren</c>);</item>
|
|
/// <item>answered anything but <c>true</c> ⇒ punten must be absent (a stale answer left
|
|
/// behind by raising <c>uren</c> is not a legal payload).</item>
|
|
/// </list>
|
|
/// Returns the Dutch detail message for a <c>400 ProblemDetails</c>, or null when complete.
|
|
/// Boundary is <c><</c>, not <c><=</c> — mirrors <c>lageUren</c>.
|
|
/// </summary>
|
|
public static string? RejectIncompleteScholing(int uren, bool? aanvullendeScholing, int? scholingPunten)
|
|
{
|
|
if (uren < ScholingThreshold && aanvullendeScholing is null)
|
|
return $"Beantwoord de vraag over aanvullende scholing: bij minder dan {ScholingThreshold} gewerkte uren is dit verplicht.";
|
|
if (aanvullendeScholing == true && (scholingPunten is null || scholingPunten < 0))
|
|
return "Vul het aantal behaalde nascholingspunten in.";
|
|
if (aanvullendeScholing != true && scholingPunten is not null)
|
|
return "Nascholingspunten horen alleen bij een gevolgde aanvullende scholing.";
|
|
return null;
|
|
}
|
|
}
|