// Wie ein Dienstverhältnis endet — und auf wessen Betreiben. // // Die Liste stand bisher in components/employees/panels/TerminatePanel.tsx und // damit an genau einer Stelle: dem Formular. Der Berichtemanager konnte // deshalb nach dem Ereignis „Austritt" fragen, aber nicht danach, *warum* — // und die Frage, die im Personalwesen zuerst kommt, ist die nach der // Fluktuation: wie viele sind gegangen, wie vielen wurde gekündigt. // // ── Warum die Zuordnung abgeleitet und nicht gespeichert wird ──────── // // Aus dem Workshop kam „ein weiteres Dropdown: freiwilliger / unfreiwilliger // Austritt". Als zweites, frei wählbares Feld liesse es sich dem Grund // widersprechen — „Entlassung, freiwillig" wäre eine erfassbare Eingabe, und // zwei Auswertungen über dieselbe Person kämen zu verschiedenen Ergebnissen. // Auf wessen Betreiben beendet wird, steckt bereits in der Beendigungsart; // das Dropdown schränkt deshalb die Auswahl ein, statt eine zweite Wahrheit // daneben zu stellen. Gespeichert wird weiterhin nur `exit_reason`. // // ── Warum es drei Gruppen sind und nicht zwei ──────────────────────── // // Zwei Gruppen decken die Liste nicht ab. Ein Befristungsablauf geschieht auf // niemandes Betreiben — er war von Anfang an vereinbart. Ein Nichtantritt ist // kein Austritt, sondern ein Verhältnis, das nie begonnen hat. Beide einer der // beiden Seiten zuzuschlagen würde jede Fluktuationsquote verfälschen, und // zwar in eine Richtung, die niemand mehr nachvollziehen kann. Sie stehen // deshalb als „Sonstige" für sich. // // Offen und im Begleitschreiben an den Kunden gestellt: ob die // einvernehmliche Auflösung — hier als freiwillig geführt, weil sie die // Zustimmung der Person voraussetzt — dort richtig steht. In der Praxis geht // ihr oft ein Wunsch des Dienstgebers voraus. export const BEENDIGUNG_NO_SHOW = "No Show"; export type Austrittsart = "freiwillig" | "unfreiwillig" | "sonstige"; export const AUSTRITTSART_LABELS: Record = { freiwillig: "Freiwilliger Austritt", unfreiwillig: "Unfreiwilliger Austritt", sonstige: "Sonstige Beendigung", }; export type Beendigungsart = { /** Der gespeicherte Wert in `employees.exit_reason`. */ wert: string; art: Austrittsart; }; export const BEENDIGUNGSARTEN: readonly Beendigungsart[] = [ { wert: "Einvernehmliche Auflösung", art: "freiwillig" }, { wert: "Kündigung AN", art: "freiwillig" }, { wert: "Pensionierung", art: "freiwillig" }, // Aus dem Workshop nachgetragen (Anforderung 1). In der Probezeit kann jede // Seite ohne Frist und ohne Grund beenden; welche es war, ist genau die // Unterscheidung, die sonst verlorenginge. { wert: "Dienstnehmerseitige Beendigung in Probezeit", art: "freiwillig" }, { wert: "Kündigung AG", art: "unfreiwillig" }, { wert: "Entlassung", art: "unfreiwillig" }, { wert: "Dienstgeberseitige Beendigung in Probezeit", art: "unfreiwillig" }, { wert: "Befristungsablauf", art: "sonstige" }, // „No Show" steht am Ende und getrennt: es ist kein Austritt im gewohnten // Sinn, sondern der Fall, dass jemand nie angetreten ist. { wert: BEENDIGUNG_NO_SHOW, art: "sonstige" }, ] as const; export const BEENDIGUNGSART_WERTE: readonly string[] = BEENDIGUNGSARTEN.map((b) => b.wert); const ART_ZU_WERT = new Map(BEENDIGUNGSARTEN.map((b) => [b.wert, b.art] as const)); /** * Auf wessen Betreiben beendet wurde — oder null, wenn der gespeicherte Grund * in keiner der Gruppen steht. * * Null ist kein Sonderfall, sondern der Normalfall für Altdaten: `exit_reason` * ist eine Textspalte ohne Prüfung, und der Massenimport schreibt hinein, was * in der Datei stand. Wer hier auf eine Gruppe rät, ordnet fremde Schreibweisen * still der falschen zu. */ export function austrittsartVon(grund: string | null | undefined): Austrittsart | null { return grund ? (ART_ZU_WERT.get(grund) ?? null) : null; } /** Die Beendigungsarten einer Gruppe — für die abhängige Auswahl im Formular. */ export function beendigungsartenZu(art: Austrittsart | null): readonly string[] { return art ? BEENDIGUNGSART_WERTE.filter((w) => ART_ZU_WERT.get(w) === art) : BEENDIGUNGSART_WERTE; }