style: format backend with dotnet format

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
eho
2026-07-03 13:39:31 +02:00
co-authored by Claude Opus 4.8
parent e82309786d
commit 1137f59f7b
17 changed files with 1135 additions and 1129 deletions
@@ -2,8 +2,8 @@ namespace BigRegister.Domain.Diplomas;
public enum QuestionType
{
JaNee,
Tekst,
JaNee,
Tekst,
}
public sealed record PolicyQuestion(string Id, string Vraag, QuestionType Type);
@@ -8,61 +8,61 @@ namespace BigRegister.Domain.Diplomas;
/// </summary>
public static class DiplomaRules
{
// RULE: study program → BIG profession.
private static readonly Dictionary<string, string> ProfessionByProgram = new(StringComparer.OrdinalIgnoreCase)
{
["geneeskunde"] = "Arts",
["verpleegkunde"] = "Verpleegkundige",
["fysiotherapie"] = "Fysiotherapeut",
["farmacie"] = "Apotheker",
["tandheelkunde"] = "Tandarts",
};
// RULE: study program → BIG profession.
private static readonly Dictionary<string, string> ProfessionByProgram = new(StringComparer.OrdinalIgnoreCase)
{
["geneeskunde"] = "Arts",
["verpleegkunde"] = "Verpleegkundige",
["fysiotherapie"] = "Fysiotherapeut",
["farmacie"] = "Apotheker",
["tandheelkunde"] = "Tandarts",
};
public static string ProfessionFor(Diploma d) =>
ProfessionByProgram.TryGetValue(d.Opleiding, out var beroep) ? beroep : "Onbekend";
public static string ProfessionFor(Diploma d) =>
ProfessionByProgram.TryGetValue(d.Opleiding, out var beroep) ? beroep : "Onbekend";
/// <summary>Professions a user may declare for a manual (unlisted) diploma.</summary>
public static IReadOnlyList<string> ManualProfessions() =>
ProfessionByProgram.Values.Distinct().ToList();
/// <summary>Professions a user may declare for a manual (unlisted) diploma.</summary>
public static IReadOnlyList<string> ManualProfessions() =>
ProfessionByProgram.Values.Distinct().ToList();
// --- Policy questions (geldigheidsvragen) ---
// --- Policy questions (geldigheidsvragen) ---
private static readonly PolicyQuestion NlTaalEngelstalig = new(
"nl-taalvaardigheid",
"Uw opleiding was Engelstalig. Beheerst u de Nederlandse taal op het vereiste niveau (B2)?",
QuestionType.JaNee);
private static readonly PolicyQuestion NlTaalEngelstalig = new(
"nl-taalvaardigheid",
"Uw opleiding was Engelstalig. Beheerst u de Nederlandse taal op het vereiste niveau (B2)?",
QuestionType.JaNee);
private static readonly PolicyQuestion NlTaalManual = new(
"nl-taalvaardigheid",
"Beheerst u de Nederlandse taal op het vereiste niveau (B2)?",
QuestionType.JaNee);
private static readonly PolicyQuestion NlTaalManual = new(
"nl-taalvaardigheid",
"Beheerst u de Nederlandse taal op het vereiste niveau (B2)?",
QuestionType.JaNee);
private static readonly PolicyQuestion DiplomaErkend = new(
"diploma-erkend",
"Is uw diploma erkend door de Nederlandse overheid (bijv. via Nuffic)?",
QuestionType.JaNee);
private static readonly PolicyQuestion DiplomaErkend = new(
"diploma-erkend",
"Is uw diploma erkend door de Nederlandse overheid (bijv. via Nuffic)?",
QuestionType.JaNee);
private static readonly PolicyQuestion Toelichting = new(
"toelichting",
"Geef een korte toelichting op uw diploma en opleiding.",
QuestionType.Tekst);
private static readonly PolicyQuestion Toelichting = new(
"toelichting",
"Geef een korte toelichting op uw diploma en opleiding.",
QuestionType.Tekst);
/// <summary>
/// RULE: an English-language diploma requires proof of Dutch proficiency (B2).
/// Add a question here to apply it to a (set of) diploma(s) — a single backend
/// change, no frontend change.
/// </summary>
public static IReadOnlyList<PolicyQuestion> QuestionsFor(Diploma d)
{
var questions = new List<PolicyQuestion>();
if (d.Engelstalig)
questions.Add(NlTaalEngelstalig);
return questions;
}
/// <summary>
/// RULE: an English-language diploma requires proof of Dutch proficiency (B2).
/// Add a question here to apply it to a (set of) diploma(s) — a single backend
/// change, no frontend change.
/// </summary>
public static IReadOnlyList<PolicyQuestion> QuestionsFor(Diploma d)
{
var questions = new List<PolicyQuestion>();
if (d.Engelstalig)
questions.Add(NlTaalEngelstalig);
return questions;
}
/// <summary>
/// RULE: a manual diploma is unverified, so the strictest (maximal) set applies.
/// </summary>
public static IReadOnlyList<PolicyQuestion> ManualQuestions() =>
new[] { NlTaalManual, DiplomaErkend, Toelichting };
/// <summary>
/// RULE: a manual diploma is unverified, so the strictest (maximal) set applies.
/// </summary>
public static IReadOnlyList<PolicyQuestion> ManualQuestions() =>
new[] { NlTaalManual, DiplomaErkend, Toelichting };
}
@@ -17,67 +17,67 @@ public sealed record DocumentCategory(
public static class DocumentRules
{
private static readonly string[] Pdf = { "application/pdf" };
private static readonly string[] PdfImage = { "application/pdf", "image/jpeg", "image/png" };
private static readonly string[] Pdf = { "application/pdf" };
private static readonly string[] PdfImage = { "application/pdf", "image/jpeg", "image/png" };
private static readonly DocumentCategory Diploma = new("diploma", "Diplomabewijs",
"Upload uw diploma als PDF-bestand.", true, Pdf, 10, false, false);
private static readonly DocumentCategory Identiteit = new("identiteit", "Identiteitsbewijs",
"Upload een kopie van uw paspoort of ID-kaart.", true, PdfImage, 10, false, true);
private static readonly DocumentCategory Taalvaardigheid = new("taalvaardigheid", "Bewijs Nederlandse taalvaardigheid",
"Upload een bewijs van uw Nederlandse taalvaardigheid op het vereiste niveau (B2).", true, PdfImage, 10, false, true);
private static readonly DocumentCategory Diploma = new("diploma", "Diplomabewijs",
"Upload uw diploma als PDF-bestand.", true, Pdf, 10, false, false);
private static readonly DocumentCategory Identiteit = new("identiteit", "Identiteitsbewijs",
"Upload een kopie van uw paspoort of ID-kaart.", true, PdfImage, 10, false, true);
private static readonly DocumentCategory Taalvaardigheid = new("taalvaardigheid", "Bewijs Nederlandse taalvaardigheid",
"Upload een bewijs van uw Nederlandse taalvaardigheid op het vereiste niveau (B2).", true, PdfImage, 10, false, true);
/// <summary>
/// The MAXIMAL set of categories a wizard can ever ask for. Used to validate an
/// upload POST (any real category must resolve) — <see cref="CategoriesFor"/>
/// decides which subset is actually presented for a given set of answers.
/// </summary>
public static IReadOnlyList<DocumentCategory> AllCategoriesFor(string wizardId) => wizardId switch
/// <summary>
/// The MAXIMAL set of categories a wizard can ever ask for. Used to validate an
/// upload POST (any real category must resolve) — <see cref="CategoriesFor"/>
/// decides which subset is actually presented for a given set of answers.
/// </summary>
public static IReadOnlyList<DocumentCategory> AllCategoriesFor(string wizardId) => wizardId switch
{
"registratie" => new[] { Diploma, Identiteit, Taalvaardigheid },
"herregistratie" => new[]
{
"registratie" => new[] { Diploma, Identiteit, Taalvaardigheid },
"herregistratie" => new[]
{
new DocumentCategory("werkervaring", "Bewijs van werkervaring",
"Upload bewijs van uw gewerkte uren (bijv. een werkgeversverklaring).", true, Pdf, 10, true, true),
new DocumentCategory("nascholing", "Nascholingscertificaten",
"Upload uw nascholingscertificaten (optioneel).", false, PdfImage, 10, true, true),
},
_ => Array.Empty<DocumentCategory>(),
};
_ => Array.Empty<DocumentCategory>(),
};
/// <summary>
/// The categories to PRESENT for a wizard, given the answers that affect required
/// documents. RULES (registratie): a diploma upload is required ONLY for a manually
/// entered diploma (a DUO diploma is verified digitally, and nothing is required
/// before a diploma is chosen); proof of Dutch taalvaardigheid is required only when
/// the applicant confirms ("ja") they meet the language requirement. Answer-agnostic
/// wizards get their full set.
/// </summary>
public static IReadOnlyList<DocumentCategory> CategoriesFor(
string wizardId, string? diplomaHerkomst = null, string? taalvaardigheid = null)
{
if (wizardId != "registratie") return AllCategoriesFor(wizardId);
var result = new List<DocumentCategory>();
if (diplomaHerkomst == "handmatig") result.Add(Diploma);
result.Add(Identiteit);
if (taalvaardigheid == "ja") result.Add(Taalvaardigheid);
return result;
}
/// <summary>
/// The categories to PRESENT for a wizard, given the answers that affect required
/// documents. RULES (registratie): a diploma upload is required ONLY for a manually
/// entered diploma (a DUO diploma is verified digitally, and nothing is required
/// before a diploma is chosen); proof of Dutch taalvaardigheid is required only when
/// the applicant confirms ("ja") they meet the language requirement. Answer-agnostic
/// wizards get their full set.
/// </summary>
public static IReadOnlyList<DocumentCategory> CategoriesFor(
string wizardId, string? diplomaHerkomst = null, string? taalvaardigheid = null)
{
if (wizardId != "registratie") return AllCategoriesFor(wizardId);
var result = new List<DocumentCategory>();
if (diplomaHerkomst == "handmatig") result.Add(Diploma);
result.Add(Identiteit);
if (taalvaardigheid == "ja") result.Add(Taalvaardigheid);
return result;
}
public static DocumentCategory? Find(string wizardId, string categoryId) =>
AllCategoriesFor(wizardId).FirstOrDefault(c => c.CategoryId == categoryId);
public static DocumentCategory? Find(string wizardId, string categoryId) =>
AllCategoriesFor(wizardId).FirstOrDefault(c => c.CategoryId == categoryId);
/// <summary>
/// Authoritative upload validation (the client check is UX-only). Returns a
/// rejection reason, or null when the file is acceptable.
/// </summary>
public static string? RejectUpload(DocumentCategory? category, string contentType, long sizeBytes)
{
if (category is null) return "Onbekende documentcategorie.";
if (!category.AcceptedTypes.Contains(contentType))
return $"Bestandstype niet toegestaan voor {category.Label}.";
if (sizeBytes > (long)category.MaxSizeMb * 1024 * 1024)
return $"Bestand is groter dan {category.MaxSizeMb} MB.";
return null;
}
/// <summary>
/// Authoritative upload validation (the client check is UX-only). Returns a
/// rejection reason, or null when the file is acceptable.
/// </summary>
public static string? RejectUpload(DocumentCategory? category, string contentType, long sizeBytes)
{
if (category is null) return "Onbekende documentcategorie.";
if (!category.AcceptedTypes.Contains(contentType))
return $"Bestandstype niet toegestaan voor {category.Label}.";
if (sizeBytes > (long)category.MaxSizeMb * 1024 * 1024)
return $"Bestand is groter dan {category.MaxSizeMb} MB.";
return null;
}
}
@@ -7,5 +7,5 @@ namespace BigRegister.Domain.Intake;
/// </summary>
public static class IntakePolicy
{
public const int ScholingThreshold = 1000;
public const int ScholingThreshold = 1000;
}
@@ -8,25 +8,25 @@ namespace BigRegister.Domain.Registrations;
/// </summary>
public static class HerregistratieRule
{
public const int WindowMonths = 12;
public const int WindowMonths = 12;
public static DateOnly? Deadline(Registration reg) =>
reg.Status.Tag == StatusTag.Geregistreerd ? reg.Status.HerregistratieDatum : null;
public static DateOnly? Deadline(Registration reg) =>
reg.Status.Tag == StatusTag.Geregistreerd ? reg.Status.HerregistratieDatum : null;
public static (bool Eligible, string? Reason) Evaluate(
Registration reg, DateOnly today, int windowMonths = WindowMonths)
{
var deadline = Deadline(reg);
if (deadline is null)
return (false, "Geen actieve registratie.");
public static (bool Eligible, string? Reason) Evaluate(
Registration reg, DateOnly today, int windowMonths = WindowMonths)
{
var deadline = Deadline(reg);
if (deadline is null)
return (false, "Geen actieve registratie.");
var windowStart = deadline.Value.AddMonths(-windowMonths);
return today >= windowStart
? (true, $"Registratie verloopt binnen {windowMonths} maanden ({deadline:yyyy-MM-dd}).")
: (false, $"Herregistratie kan vanaf {windowStart:yyyy-MM-dd}.");
}
var windowStart = deadline.Value.AddMonths(-windowMonths);
return today >= windowStart
? (true, $"Registratie verloopt binnen {windowMonths} maanden ({deadline:yyyy-MM-dd}).")
: (false, $"Herregistratie kan vanaf {windowStart:yyyy-MM-dd}.");
}
/// <summary>Invariant: a non-active status must not carry a herregistratie date.</summary>
public static bool IsStatusConsistent(RegistrationStatus s) =>
s.Tag != StatusTag.Geregistreerd || s.HerregistratieDatum is not null;
/// <summary>Invariant: a non-active status must not carry a herregistratie date.</summary>
public static bool IsStatusConsistent(RegistrationStatus s) =>
s.Tag != StatusTag.Geregistreerd || s.HerregistratieDatum is not null;
}
@@ -3,9 +3,9 @@ namespace BigRegister.Domain.Registrations;
/// <summary>The three states a BIG registration can be in.</summary>
public enum StatusTag
{
Geregistreerd,
Geschorst,
Doorgehaald,
Geregistreerd,
Geschorst,
Doorgehaald,
}
/// <summary>
@@ -9,29 +9,29 @@ namespace BigRegister.Domain.Submissions;
/// </summary>
public static class SubmissionRules
{
// RULE: a manually entered diploma cannot be auto-verified.
public static string? RejectRegistratie(string diplomaHerkomst) =>
diplomaHerkomst == "handmatig"
? "Een handmatig ingevoerd diploma kan niet automatisch worden geverifieerd. Uw aanvraag is doorgestuurd voor handmatige beoordeling."
: null;
// RULE: a manually entered diploma cannot be auto-verified.
public static string? RejectRegistratie(string diplomaHerkomst) =>
diplomaHerkomst == "handmatig"
? "Een handmatig ingevoerd diploma kan niet automatisch worden geverifieerd. Uw aanvraag is doorgestuurd voor handmatige beoordeling."
: null;
// RULE: an application reporting zero worked hours is rejected.
public static string? RejectZeroUren(int uren) =>
uren == 0 ? "Aanvraag afgewezen: geen gewerkte uren geregistreerd." : null;
// RULE: an application reporting zero worked hours is rejected.
public static string? RejectZeroUren(int uren) =>
uren == 0 ? "Aanvraag afgewezen: geen gewerkte uren geregistreerd." : null;
private static readonly Regex PostcodePattern =
new(@"^[1-9]\d{3}\s?[A-Z]{2}$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex PostcodePattern =
new(@"^[1-9]\d{3}\s?[A-Z]{2}$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
// RULE: a change request needs a street and a well-formed Dutch postcode. The
// server re-validates format authoritatively (the FE check is UX-only).
public static string? RejectChangeRequest(string straat, string postcode)
{
if (string.IsNullOrWhiteSpace(straat)) return "Vul straat en huisnummer in.";
if (!PostcodePattern.IsMatch(postcode?.Trim() ?? "")) return "Voer een geldige postcode in, bijv. 1234 AB.";
return null;
}
// RULE: a change request needs a street and a well-formed Dutch postcode. The
// server re-validates format authoritatively (the FE check is UX-only).
public static string? RejectChangeRequest(string straat, string postcode)
{
if (string.IsNullOrWhiteSpace(straat)) return "Vul straat en huisnummer in.";
if (!PostcodePattern.IsMatch(postcode?.Trim() ?? "")) return "Voer een geldige postcode in, bijv. 1234 AB.";
return null;
}
public static string NewReference() =>
// ponytail: random reference is fine for a demo; a real system reserves it transactionally.
"BIG-2026-" + Random.Shared.Next(100_000, 1_000_000);
public static string NewReference() =>
// ponytail: random reference is fine for a demo; a real system reserves it transactionally.
"BIG-2026-" + Random.Shared.Next(100_000, 1_000_000);
}