Files
atomic-design-poc/backend/src/BigRegister.Api/Domain/Intake/IntakePolicy.cs
T
ehoandClaude Opus 5 194cccfd02 refactor: rename Application → Aanvraag across the wire (Step 1/8)
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>
2026-09-04 14:33:16 +02:00

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>&lt;</c>, not <c>&lt;=</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;
}
}