Workshop-Anforderungen, erster Teil: was ohne Migration geht
Anforderung 1 — Freiwilliger vs unfreiwilliger Austritt. Die Liste der Beendigungsarten zieht aus TerminatePanel.tsx nach lib/beendigung.ts um: der Berichtemanager braucht sie ebenso, und zwei Listen liefen auseinander. Zwei neue Arten (Beendigung in der Probezeit, je Seite). Auf wessen Betreiben beendet wurde, wird aus der Art **abgeleitet** und nicht daneben gespeichert — als zweites freies Feld liesse sich "Entlassung, freiwillig" erfassen. Das Dropdown im Formular schraenkt die Auswahl darunter ein. Drei Gruppen statt zwei: Befristungsablauf geschieht auf niemandes Betreiben, ein Nichtantritt ist kein Austritt. Beide einer Seite zuzuschlagen wuerde jede Fluktuationsquote verfaelschen. Anforderung 2 — Namensfilter in "Anstehend", ab neun Eintraegen. Anforderung 3 — die zwei Unterschriftenfelder im gedruckten Blatt sind weg; "Firmenfahrzeug" steht in beiden Checklisten. has_dienstwagen sagt, ob eines zusteht, nicht ob es uebergeben wurde. Anforderung 4 — "+794 weitere" ist ein Knopf geworden; die Namen waren vorher nur ueber den Export erreichbar. Stammdatenaenderung und Gehaltsanpassung stehen nicht mehr zur Auswahl: die eine entsteht bei jeder geaenderten Telefonnummer, die andere ist ein totes Ereignis, seit das Gehalt in Loga liegt. Neu ist der Untertyp — Beendigungsart beim Austritt, Art der Abwesenheit bei der Langzeitabwesenheit, im Bericht und im Export. Anforderung 10 — zwei Kacheln. "Aktives Dienstverhaeltnis" ist nicht dasselbe wie "Aktive Mitarbeiter:innen": dort steht, wer heute arbeitet, hier, mit wem ein Vertrag laeuft. Sichtbar waren 806 und 10, addieren musste man selbst.
This commit is contained in:
@@ -7,23 +7,23 @@ import { Button } from "@/components/ui/Button";
|
||||
import { SelectField, TextField, TextareaField } from "@/components/ui/Field";
|
||||
import { SlideOver } from "@/components/ui/SlideOver";
|
||||
import { useToast } from "@/components/ui/Toast";
|
||||
import {
|
||||
AUSTRITTSART_LABELS,
|
||||
BEENDIGUNG_NO_SHOW,
|
||||
BEENDIGUNGSART_WERTE,
|
||||
austrittsartVon,
|
||||
beendigungsartenZu,
|
||||
type Austrittsart,
|
||||
} from "@/lib/beendigung";
|
||||
import type { Database } from "@/lib/types";
|
||||
import { fmtDate, fmtName } from "@/lib/format";
|
||||
|
||||
type EmployeeRow = Database["public"]["Tables"]["employees"]["Row"];
|
||||
|
||||
// „No Show" steht am Ende und getrennt: es ist kein Austritt im gewohnten
|
||||
// Sinn, sondern der Fall, dass jemand nie angetreten ist.
|
||||
const NO_SHOW = "No Show";
|
||||
const EXIT_REASONS = [
|
||||
"Einvernehmliche Auflösung",
|
||||
"Kündigung AN",
|
||||
"Kündigung AG",
|
||||
"Befristungsablauf",
|
||||
"Pensionierung",
|
||||
"Entlassung",
|
||||
NO_SHOW,
|
||||
];
|
||||
// Die Liste steht in lib/beendigung.ts, nicht mehr hier: der Berichtemanager
|
||||
// braucht sie ebenso, und zwei Listen liefen auseinander.
|
||||
const NO_SHOW = BEENDIGUNG_NO_SHOW;
|
||||
|
||||
type TerminatePanelProps = {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
@@ -38,7 +38,12 @@ export function TerminatePanel({ open, onClose, employee, directReportCount }: T
|
||||
// Wer noch gar nicht angefangen hat, tritt fast nie aus einem anderen Grund
|
||||
// aus. Die Vorbelegung nimmt den wahrscheinlichen Fall vorweg, ohne die
|
||||
// übrigen zu verstellen.
|
||||
const [reason, setReason] = useState(employee.status === "Geplant" ? NO_SHOW : EXIT_REASONS[0]);
|
||||
const [reason, setReason] = useState(employee.status === "Geplant" ? NO_SHOW : BEENDIGUNGSART_WERTE[0]);
|
||||
// „Alle" statt einer Vorauswahl: die Einschränkung ist eine Hilfe beim
|
||||
// Suchen, keine Pflichtangabe. Wer die gewünschte Art auswendig kennt,
|
||||
// soll sie unmittelbar wählen können.
|
||||
const [austrittsart, setAustrittsart] = useState<Austrittsart | "">("");
|
||||
const waehlbar = beendigungsartenZu(austrittsart || null);
|
||||
const [note, setNote] = useState("");
|
||||
const [pending, setPending] = useState(false);
|
||||
|
||||
@@ -113,11 +118,36 @@ export function TerminatePanel({ open, onClose, employee, directReportCount }: T
|
||||
{directReportCount} direkte Berichte werden automatisch der nächsthöheren Führungskraft zugeordnet.
|
||||
</div>
|
||||
)}
|
||||
{/* Die Austrittsart wählt nicht mit, sie engt ein. Gespeichert wird
|
||||
allein die Beendigungsart; auf wessen Betreiben beendet wurde,
|
||||
leitet lib/beendigung.ts daraus ab. Als zweites freies Feld liesse
|
||||
sich „Entlassung, freiwillig" erfassen, und zwei Auswertungen über
|
||||
dieselbe Person kämen zu verschiedenen Ergebnissen. */}
|
||||
<SelectField
|
||||
label="Austrittsart"
|
||||
value={austrittsart}
|
||||
onChange={(v) => {
|
||||
const neu = (v || "") as Austrittsart | "";
|
||||
setAustrittsart(neu);
|
||||
// Passt der bisher gewählte Grund nicht mehr zur Einschränkung,
|
||||
// wandert die Auswahl auf den ersten passenden. Stehenzulassen,
|
||||
// was in der Liste nicht mehr sichtbar ist, wäre ein Formular,
|
||||
// das etwas anderes absendet, als es zeigt.
|
||||
const erlaubt = beendigungsartenZu(neu || null);
|
||||
if (!erlaubt.includes(reason)) setReason(erlaubt[0]);
|
||||
}}
|
||||
options={[
|
||||
{ value: "", label: "Alle Beendigungsarten" },
|
||||
...(Object.keys(AUSTRITTSART_LABELS) as Austrittsart[]).map((a) => ({ value: a, label: AUSTRITTSART_LABELS[a] })),
|
||||
]}
|
||||
hint="Schränkt die Auswahl darunter ein. Gespeichert wird die Beendigungsart."
|
||||
/>
|
||||
<SelectField
|
||||
label="Beendigungsart"
|
||||
value={reason}
|
||||
onChange={setReason}
|
||||
options={EXIT_REASONS.map((r) => ({ value: r, label: r === NO_SHOW ? "No Show (nicht angetreten)" : r }))}
|
||||
options={waehlbar.map((r) => ({ value: r, label: r === NO_SHOW ? "No Show (nicht angetreten)" : r }))}
|
||||
hint={austrittsartVon(reason) ? AUSTRITTSART_LABELS[austrittsartVon(reason)!] : undefined}
|
||||
/>
|
||||
<TextField
|
||||
label={istNoShow ? "Wirksam am (Eintrittstag)" : "Austrittsdatum"}
|
||||
|
||||
Reference in New Issue
Block a user