Mitarbeiterart als zweite Achse neben der Beschaeftigtengruppe

Anforderung 9 aus dem Workshop. Migration 20260915140000.

Im Dokument standen die beiden untereinander:

    Arbeiter, Angestellte, Lehrlinge
    Standard / Praktikant / Geringfuegige Beschaeftigung / Altersteilzeit

Die erste Zeile gibt es schon als worker_type, Lehrling seit 20260910140000.
Die zweite ist eine andere Frage: nicht *als was* jemand angestellt ist,
sondern *in welcher Form*. Beide gelten gleichzeitig — ein Praktikant ist
Arbeiter oder Angestellter, nicht statt dessen. In eine Liste gepresst
muesste man sich fuer eine der Antworten entscheiden und verloere die andere.

NOT NULL mit Vorgabe "Standard": jede Person ist in irgendeiner Form
beschaeftigt, und "nicht erfasst" waere keine Aussage, sondern eine Luecke,
die sich durch jede Auswertung zieht. Der Bestand bekommt damit einen
sichtbaren, korrigierbaren Ausgangswert statt eines leeren Feldes.

Die vier Funktionen wurden vollstaendig neu geschrieben. Die Selbstpruefung
haelt deshalb auch die Felder der vorigen Migration fest: eines beim
Uebertragen zu verlieren waere ein Fehler, der nirgends auffiele — die
Oberflaeche schickte den Wert weiter, und die Funktion ignorierte ihn.
This commit is contained in:
2026-09-15 22:52:44 +02:00
parent c25c16e372
commit cf0ea51f47
13 changed files with 851 additions and 2 deletions

View File

@@ -0,0 +1,46 @@
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { MITARBEITERART_STANDARD, MITARBEITERARTEN, istMitarbeiterart } from "@/lib/mitarbeiterart";
// Dieselbe Vorsichtsmassnahme wie bei den Personenkreisen: die Liste steht in
// der Migration als CHECK und hier für die Oberfläche. Laufen die beiden
// auseinander, bietet das Formular einen Wert an, den die Datenbank abweist —
// und die Benutzerin sieht einen Fehler aus dem Maschinenraum.
const MIGRATION = join(process.cwd(), "db/migrations/20260915140000_mitarbeiterart.sql");
function werteAusDerBedingung(): string[] {
const sql = readFileSync(MIGRATION, "utf8");
const block = sql.match(/chk_mitarbeiterart\s+check[\s\S]*?\);/)?.[0];
expect(block, "Die Bedingung steht nicht mehr in der Migration").toBeDefined();
return [...block!.matchAll(/'([^']+)'/g)].map((m) => m[1]);
}
describe("Die Mitarbeiterarten", () => {
it("stimmen mit der Bedingung in der Datenbank überein", () => {
expect(new Set(werteAusDerBedingung())).toEqual(new Set(MITARBEITERARTEN));
});
it("führen Standard als Vorgabe", () => {
// Die Spalte ist NOT NULL mit genau diesem Vorgabewert; weicht die
// Oberfläche davon ab, bekäme der Bestand etwas anderes als die neuen
// Zeilen.
expect(MITARBEITERARTEN).toContain(MITARBEITERART_STANDARD);
expect(readFileSync(MIGRATION, "utf8")).toContain("not null default 'Standard'");
});
it("weisen zurück, was nicht in der Liste steht", () => {
expect(istMitarbeiterart("Altersteilzeit")).toBe(true);
expect(istMitarbeiterart("Teilzeit")).toBe(false);
expect(istMitarbeiterart(null)).toBe(false);
});
it("sind etwas anderes als die Beschäftigtengruppe", () => {
// Die beiden Achsen dürfen keine Werte teilen: täten sie es, liesse sich
// aus einem Wert nicht mehr ablesen, welche Frage er beantwortet.
for (const wert of ["Angestellte:r", "Arbeiter:in", "Lehrling"]) {
expect(MITARBEITERARTEN).not.toContain(wert);
}
});
});