Cornerstone fuehrt jede Person unter einer eigenen Kennung. Der Export dorthin trug in "User ID" und "Username" bisher die Alpenwerk-UUID -- richtig, solange es nichts Besseres gab, aber nicht die Kennung, unter der Cornerstone die Person kennt. Jetzt steht dort diese Spalte. Freiwillig, weil die Zuordnungstabelle des Kunden fuer 434 der 784 Personen keine Kennung liefert. Eindeutig, weil eine Kennung genau einer Person gehoert. Als Text, weil fuehrende Nullen in einer numerischen Spalte verlorengingen. Ohne hinterlegte Kennung bleiben User ID und Username **leer**. Ein Rueckfall auf die UUID braechte zwei Kennungsarten in eine Datei, ohne dass es auffiele, und legte in Cornerstone eine zweite Person neben der bestehenden an. Eine fehlende Angabe soll fehlen; dafuer gibt es einen eigenen Test. Fuenf Funktionen mussten mit -- dieselbe Liste und derselbe Grund wie bei der Firmen-E-Mail: hire_employee und rehire_employee teilen sich den Schritt "Person", change_employee_data macht das Feld aenderbar, apply_due_pending_changes sorgt dafuer, dass eine datierte Aenderung nicht verfaellt, app_feld_karte haelt den Eintrag in der Historie richtigstellbar. Die Migration ist wieder erzeugt, nicht abgeschrieben, und prueft jede der fuenf einzeln. Erfasst wird das Feld in der Akte, in "Daten aendern", bei Einstellung und Wiedereintritt sowie ueber den Massenimport; es steht im Mitarbeiterexport und fuellt im Cornerstone-Export User ID und Username.
88 lines
4.1 KiB
TypeScript
88 lines
4.1 KiB
TypeScript
import { AngehoerigeSection } from "@/components/employees/AngehoerigeSection";
|
||
import { NotfallkontaktSection } from "@/components/employees/NotfallkontaktSection";
|
||
import { brauchtAufenthaltstitel } from "@/lib/countries";
|
||
import { fmtAge, fmtDate } from "@/lib/format";
|
||
import type { Database } from "@/lib/types";
|
||
|
||
type EmployeeRow = Database["public"]["Tables"]["employees"]["Row"];
|
||
type Location = Database["public"]["Tables"]["locations"]["Row"];
|
||
type Dependent = Database["public"]["Tables"]["employee_dependents"]["Row"];
|
||
|
||
export function StammdatenTab({ employee, location, dependents }: { employee: EmployeeRow; location?: Location; dependents: Dependent[] }) {
|
||
// Defensive against a DB that hasn't received the title_prefix/title_suffix
|
||
// migration yet — select("*") simply omits unknown columns, so these can
|
||
// be undefined rather than the empty array the column default implies.
|
||
const prefixe = employee.title_prefix ?? [];
|
||
const suffixe = employee.title_suffix ?? [];
|
||
|
||
// Feld für Feld dieselbe Liste wie im Abschnitt „Person" von „Daten
|
||
// ändern", in derselben Reihenfolge.
|
||
//
|
||
// Vorher fasste die Anzeige zusammen: Titel in einer Zeile, Adresse mit
|
||
// Postleitzahl und Ort verschmolzen, Vor- und Nachname gar nicht — die
|
||
// standen nur in der Kopfzeile. Wer eine Angabe prüfen wollte, musste den
|
||
// Änderungsdialog öffnen, um sie überhaupt zu sehen, und stand dann schon
|
||
// in einem Formular. Was sich ändern lässt, soll sich auch ansehen lassen.
|
||
const rows: [string, string][] = [
|
||
["Personalnummer", String(employee.personnel_number)],
|
||
["Vorname", employee.first_name],
|
||
["Nachname", employee.last_name],
|
||
["Titel (vorangestellt)", prefixe.length > 0 ? prefixe.join(", ") : "–"],
|
||
["Titel (nachgestellt)", suffixe.length > 0 ? suffixe.join(", ") : "–"],
|
||
["Geschlecht", employee.gender === "m" ? "männlich" : "weiblich"],
|
||
["Geburtsdatum", `${fmtDate(employee.birth_date)} (${fmtAge(employee.birth_date)} Jahre)`],
|
||
["SV-Nummer", employee.sv_nummer ?? "–"],
|
||
["Staatsbürgerschaft", employee.nationality],
|
||
// Nur, wo er verlangt ist. Bei einer österreichischen Staatsbürger-
|
||
// schaft wäre die Zeile „Aufenthaltstitel: Nein" keine Auskunft,
|
||
// sondern eine Frage, die sich nicht stellt.
|
||
...(brauchtAufenthaltstitel(employee.nationality)
|
||
? ([
|
||
[
|
||
"Aufenthaltstitel",
|
||
employee.hat_aufenthaltstitel
|
||
? employee.aufenthaltstitel_bis
|
||
? `Ja, bis ${fmtDate(employee.aufenthaltstitel_bis)}`
|
||
: "Ja (unbefristet oder nicht erfasst)"
|
||
: "Nein",
|
||
],
|
||
] as [string, string][])
|
||
: []),
|
||
["Adresse", employee.address ?? "–"],
|
||
["Postleitzahl", employee.postal_code ?? "–"],
|
||
["Ort", employee.city ?? "–"],
|
||
["Land", employee.address_country ?? "–"],
|
||
["Private E-Mail", employee.email ?? "–"],
|
||
["Firmen-E-Mail", employee.company_email ?? "–"],
|
||
["Cornerstone-ID", employee.cornerstone_id ?? "–"],
|
||
["Private Telefonnummer", employee.phone ?? "–"],
|
||
// Der Standort ist keine Angabe zur Person, sondern die Betriebsstätte —
|
||
// er steht deshalb am Ende und nicht zwischen Adresse und Land, wo man
|
||
// ihn für den Wohnort halten könnte.
|
||
["Standort", location ? `${location.name} (${location.country})` : "–"],
|
||
];
|
||
return (
|
||
<div className="flex flex-col gap-6">
|
||
<dl className="grid grid-cols-1 gap-x-8 gap-y-4 sm:grid-cols-2 lg:grid-cols-3">
|
||
{rows.map(([label, value]) => (
|
||
<div key={label}>
|
||
<dt className="text-xs font-semibold uppercase tracking-wide text-ink-muted">{label}</dt>
|
||
<dd className="mt-1 text-sm text-ink">{value}</dd>
|
||
</div>
|
||
))}
|
||
</dl>
|
||
|
||
<AngehoerigeSection employeeId={employee.id} dependents={dependents} />
|
||
|
||
<NotfallkontaktSection
|
||
employeeId={employee.id}
|
||
kontakt={{
|
||
name: employee.emergency_contact_name,
|
||
telefon: employee.emergency_contact_phone,
|
||
verhaeltnis: employee.emergency_contact_relation,
|
||
}}
|
||
/>
|
||
</div>
|
||
);
|
||
}
|