diff --git a/components/employees/tabs/VertragTab.tsx b/components/employees/tabs/VertragTab.tsx index cce7547..84ce60e 100644 --- a/components/employees/tabs/VertragTab.tsx +++ b/components/employees/tabs/VertragTab.tsx @@ -1,3 +1,4 @@ +import { dienstwagenLabel } from "@/lib/dienstwagen"; import { fmtDate } from "@/lib/format"; import type { Database } from "@/lib/supabase/types"; @@ -13,12 +14,11 @@ const PAYGRADE_LABELS: Record = { }; export function VertragTab({ employee }: { employee: EmployeeRow }) { - const flags = [ - employee.is_betriebsrat && "Betriebsrat", - employee.has_dienstwagen && "Dienstwagen", - employee.is_laterale_fuehrung && "Laterale Führung", - employee.is_c_level && "C-Level", - ].filter(Boolean); + // Früher stand hier eine einzige Zeile „Merkmale" mit allem, was zutraf, + // durch Kommas getrennt — und ein Gedankenstrich, wenn nichts zutraf. Damit + // liess sich nicht ablesen, ob jemand *keinen* Dienstwagen hat oder ob + // niemand die Frage je beantwortet hat. Jedes Merkmal steht jetzt für sich, + // mit Ja oder Nein, wie jede andere Zeile auf diesem Blatt auch. const rows: [string, string][] = [ ["Eintrittsdatum", fmtDate(employee.entry_date)], ["Vertragsart", employee.contract_type === "befristet" ? `befristet bis ${fmtDate(employee.contract_end_date)}` : "unbefristet"], @@ -29,7 +29,12 @@ export function VertragTab({ employee }: { employee: EmployeeRow }) { ["Paygrade", PAYGRADE_LABELS[employee.paygrade] ?? employee.paygrade], ["Angestellte:r / Arbeiter:in", employee.worker_type ?? "–"], ["Arbeitstage", employee.work_days?.join(", ") || "–"], - ["Merkmale", flags.length > 0 ? flags.join(", ") : "–"], + // Beim Dienstwagen steht die Antriebsart statt eines blossen „Ja" — das + // war die Frage dahinter, seit E-Fahrzeuge getrennt zu führen sind. + ["Dienstwagen", employee.has_dienstwagen ? dienstwagenLabel(employee.dienstwagen_art) : "Nein"], + ["Betriebsrat", employee.is_betriebsrat ? "Ja" : "Nein"], + ["Laterale Führung", employee.is_laterale_fuehrung ? "Ja" : "Nein"], + ["C-Level", employee.is_c_level ? "Ja" : "Nein"], ]; if (employee.exit_date) rows.push(["Austrittsdatum", fmtDate(employee.exit_date)]); diff --git a/components/hire/StepSummary.tsx b/components/hire/StepSummary.tsx index 5d816dd..5d086f3 100644 --- a/components/hire/StepSummary.tsx +++ b/components/hire/StepSummary.tsx @@ -1,3 +1,4 @@ +import { dienstwagenLabel } from "@/lib/dienstwagen"; import { fmtDate, fmtFullName } from "@/lib/format"; import type { OpenPositionResolved } from "@/lib/positions"; import type { HireDraftData } from "./types"; @@ -21,7 +22,7 @@ export function StepSummary({ draft, selectedPosition, locations }: StepSummaryP const location = locations.find((l) => l.id === draft.locationId); const flags = [ draft.isBetriebsrat && "Betriebsrat", - draft.hasDienstwagen && `Dienstwagen (${draft.dienstwagenArt === "Elektro" ? "E-KFZ" : "Verbrenner"})`, + draft.hasDienstwagen && `Dienstwagen (${dienstwagenLabel(draft.dienstwagenArt)})`, draft.isLateraleFuehrung && "Laterale Führung", draft.isCLevel && "C-Level", ].filter(Boolean); diff --git a/lib/dienstwagen.ts b/lib/dienstwagen.ts new file mode 100644 index 0000000..cb12a2b --- /dev/null +++ b/lib/dienstwagen.ts @@ -0,0 +1,17 @@ +import type { DienstwagenArt } from "./supabase/types"; + +// Wie ein Dienstwagen benannt wird. +// +// Gespeichert steht „Elektro"; gesprochen wird von einem E-KFZ, und danach +// wird auch gefragt. Die Beschriftung stand an drei Stellen einzeln — im +// Auswahlfeld, in der Zusammenfassung des Einstellungsassistenten und auf dem +// Vertragsblatt. Drei Kopien einer Beschriftung laufen auseinander, und dann +// heisst dasselbe Auto je nach Bildschirm anders. + +export function dienstwagenLabel(art: DienstwagenArt | null | undefined): string { + if (art === "Elektro") return "E-KFZ"; + if (art === "Verbrenner") return "Verbrenner"; + // Der CHECK erlaubt es nicht, aber gelesen wird auch, was jemand über den + // Import hineingelegt hat. + return art ?? "–"; +} diff --git a/tests/components/VertragTab.test.tsx b/tests/components/VertragTab.test.tsx new file mode 100644 index 0000000..3532fc3 --- /dev/null +++ b/tests/components/VertragTab.test.tsx @@ -0,0 +1,104 @@ +import { render, screen } from "@testing-library/react"; +import { describe, expect, it } from "vitest"; +import { VertragTab } from "@/components/employees/tabs/VertragTab"; +import type { Database } from "@/lib/supabase/types"; + +type EmployeeRow = Database["public"]["Tables"]["employees"]["Row"]; + +// Auf dem Vertragsblatt stand ein Feld „Merkmale" mit allem Zutreffenden, +// durch Kommas getrennt — und einem Gedankenstrich, wenn nichts zutraf. +// Daraus liess sich nicht ablesen, ob jemand keinen Dienstwagen hat oder ob +// die Frage nie beantwortet wurde. Und beim Dienstwagen fehlte, worum es +// eigentlich geht: ob Verbrenner oder E-KFZ. + +function mitarbeiter(teil: Partial = {}): EmployeeRow { + return { + id: "e1", + personnel_number: 3038, + first_name: "Hannah", + last_name: "Winkler", + gender: "w", + birth_date: "1990-04-01", + sv_nummer: null, + nationality: "Österreich", + address: null, + address_country: null, + postal_code: null, + city: null, + email: null, + phone: null, + job_title: "IT-Security-Spezialist:in", + location_id: "l1", + employment_type: "Vollzeit", + weekly_hours: 38.5, + monthly_salary_gross: null, + contract_type: "unbefristet", + contract_end_date: null, + paygrade: "C", + source: "Extern", + status: "Aktiv", + entry_date: "2017-07-15", + exit_date: null, + exit_reason: null, + karenz_start_date: null, + karenz_return_date: null, + absence_type: null, + avatar_color: null, + worker_type: "Angestellte:r", + collective_agreement: "Handel", + work_days: ["Mo", "Di", "Mi", "Do", "Fr"], + is_betriebsrat: false, + has_dienstwagen: false, + dienstwagen_art: null, + is_laterale_fuehrung: false, + is_c_level: false, + title_prefix: [], + title_suffix: [], + emergency_contact_name: null, + emergency_contact_phone: null, + emergency_contact_relation: null, + created_at: "2017-07-15T00:00:00.000Z", + updated_at: "2017-07-15T00:00:00.000Z", + ...teil, + } as EmployeeRow; +} + +/** Der Wert, der unter einer Beschriftung steht. */ +function wertZu(label: string): string { + return screen.getByText(label).parentElement!.querySelector("dd")!.textContent ?? ""; +} + +describe("VertragTab — Merkmale", () => { + it("führt jedes Merkmal als eigene Zeile, nicht als Aufzählung", () => { + render(); + for (const label of ["Dienstwagen", "Betriebsrat", "Laterale Führung", "C-Level"]) { + expect(screen.getByText(label)).toBeInTheDocument(); + } + expect(screen.queryByText("Merkmale")).not.toBeInTheDocument(); + }); + + it("sagt Nein, statt das Feld leer zu lassen", () => { + // „–" liesse offen, ob niemand die Frage beantwortet hat. + render(); + expect(wertZu("Dienstwagen")).toBe("Nein"); + expect(wertZu("Betriebsrat")).toBe("Nein"); + expect(wertZu("C-Level")).toBe("Nein"); + }); + + it("nennt beim Dienstwagen die Antriebsart statt eines blossen Ja", () => { + render(); + expect(wertZu("Dienstwagen")).toBe("E-KFZ"); + }); + + it("unterscheidet den Verbrenner davon", () => { + render(); + expect(wertZu("Dienstwagen")).toBe("Verbrenner"); + }); + + it("zeigt gesetzte Merkmale als Ja", () => { + render(); + expect(wertZu("Betriebsrat")).toBe("Ja"); + expect(wertZu("C-Level")).toBe("Ja"); + expect(wertZu("Laterale Führung")).toBe("Nein"); + }); +});