Files
alpenwerk-hr/lib/absence.ts
Maximilian Stubhan 8282d7f581 Rename Karenz to Langzeitabwesenheit and record its type
Karenz was doing duty as the name for every kind of extended absence, but
the cases behave differently in payroll and reporting — Wochenhilfe, a
Präsenzdienst, a long sick leave and a sabbatical are not the same thing.
The concept is now called Langzeitabwesenheit and carries which kind it is.

- employees.absence_type, constrained to the thirteen kinds. start_karenz
  stores it on both paths (written straight away, or parked in the
  pending_org_changes payload when the absence starts later);
  record_karenz_return and the karenz_return branch of
  apply_due_pending_changes clear it, so a returned employee does not keep
  looking like they are still away. It also reaches employee_history, the
  audit log and the employee export.
- The status enum value stays 'Karenz'. Postgres can rename an enum value in
  place, but every stored function body that spells it would then reference
  a value that no longer exists — a dozen functions across fifteen
  migrations, rewritten for a label. The mapping lives in lib/absence.ts
  instead, which is the single place the UI reads the display name from.
- Where a kind is recorded the chip shows it — "Bildungskarenz" says more
  than "Langzeitabwesenheit". Absences predating the field have none and
  fall back to the generic name rather than to a guess, and a value outside
  the list is dropped rather than echoed into the UI.
- The export prints the display name, not the raw enum: a payroll hand-off
  reading "Karenz" for what the app calls Langzeitabwesenheit only causes
  questions. Audit filter options keep their stored values and change only
  their labels.
- The seed spreads the twelve absences across the kinds; all of them being
  Karenz would leave any breakdown by kind invisible.
2026-07-25 14:34:28 +02:00

54 lines
1.7 KiB
TypeScript

import type { EmploymentStatus } from "./supabase/types";
// Langzeitabwesenheit.
//
// The database still stores the employment status as 'Karenz' — renaming an
// enum value would mean rewriting every stored function that spells it, for
// a label change (see supabase/migrations/*_absence_type.sql). So the value
// is mapped to its display name here, in the one place the UI reads it from.
export const ABSENCE_TYPES = [
"Wochenhilfe (Mutterschutz)",
"Elternkarenz (inkl. Väterkarenz)",
"Papamonat",
"Bildungskarenz",
"Bildungsteilzeit",
"Präsenzdienst",
"Zivildienst",
"Langer Krankenstand",
"Wiedereingliederungsteilzeit",
"Pflegekarenz",
"Pflegeteilzeit",
"Familienhospizkarenz",
"Sabbatical",
] as const;
export type AbsenceType = (typeof ABSENCE_TYPES)[number];
export function isAbsenceType(value: string | null | undefined): value is AbsenceType {
return ABSENCE_TYPES.includes(value as AbsenceType);
}
/** Display names for the stored status values. */
const STATUS_LABELS: Record<EmploymentStatus, string> = {
Aktiv: "Aktiv",
Karenz: "Langzeitabwesenheit",
Geplant: "Geplant",
Ausgetreten: "Ausgetreten",
};
export function statusLabel(status: EmploymentStatus): string {
return STATUS_LABELS[status] ?? status;
}
/**
* The chip and the detail header show the specific kind when it is known —
* "Bildungskarenz" says more than "Langzeitabwesenheit". Absences recorded
* before the type existed have none, and fall back to the generic name
* rather than to a guess.
*/
export function absenceLabel(status: EmploymentStatus, absenceType: string | null | undefined): string {
if (status !== "Karenz") return statusLabel(status);
return isAbsenceType(absenceType) ? absenceType : STATUS_LABELS.Karenz;
}