Die Cornerstone-ID als eigenes, freiwilliges Feld
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.
This commit is contained in:
@@ -160,6 +160,7 @@ export type CornerstoneQuelle = {
|
||||
title_suffix: string[];
|
||||
gender: string;
|
||||
company_email: string | null;
|
||||
cornerstone_id: string | null;
|
||||
address: string | null;
|
||||
postal_code: string | null;
|
||||
city: string | null;
|
||||
@@ -187,19 +188,24 @@ export type CornerstoneKontext = {
|
||||
export function baueCornerstoneZeile(p: CornerstoneQuelle, k: CornerstoneKontext): CornerstoneZeile {
|
||||
// Zwei Kennungen, zwei Herkünfte:
|
||||
//
|
||||
// User ID + Username die UUID aus Alpenwerk (employees.id)
|
||||
// User ID + Username die Cornerstone-ID (employees.cornerstone_id)
|
||||
// Local System ID die Personalnummer, wie LOGA sie vergibt
|
||||
//
|
||||
// Benutzername und Benutzer-ID sind in Alpenwerk stets derselbe Wert —
|
||||
// liefen sie auseinander, zeigte Cornerstone zwei Kennungen für eine
|
||||
// Person, und jeder Verweis darauf träfe womöglich die falsche.
|
||||
// Benutzername und Benutzer-ID sind stets derselbe Wert — liefen sie
|
||||
// auseinander, zeigte Cornerstone zwei Kennungen für eine Person, und
|
||||
// jeder Verweis darauf träfe womöglich die falsche.
|
||||
//
|
||||
// Die UUID und nicht die Personalnummer, weil sie die Kennung ist, die
|
||||
// sich nie ändert: eine Personalnummer kann berichtigt werden, und dann
|
||||
// wäre die Person in Cornerstone eine andere.
|
||||
// Hier stand die Alpenwerk-UUID, solange es nichts Besseres gab. Seit
|
||||
// 20260928100000 führt Alpenwerk die Kennung mit, unter der Cornerstone
|
||||
// die Person selbst kennt; die UUID sagte dort niemandem etwas.
|
||||
//
|
||||
// **Leer, wenn keine hinterlegt ist.** Ein Rückfall auf die UUID brächte
|
||||
// zwei Kennungsarten in eine Datei, ohne dass es jemandem auffiele — und
|
||||
// legte in Cornerstone eine zweite Person neben der bestehenden an. Eine
|
||||
// fehlende Kennung ist eine fehlende Angabe und soll als solche auffallen.
|
||||
//
|
||||
// Der Anmeldename des Verzeichnisdienstes steht nur im Customfield AD.
|
||||
const kennung = p.id;
|
||||
const kennung = p.cornerstone_id ?? "";
|
||||
const nummer = String(p.personnel_number);
|
||||
const adName = benutzername(p.first_name, p.last_name);
|
||||
const kst = p.position_id ? k.kostenstelle.get(p.position_id) : undefined;
|
||||
|
||||
@@ -58,7 +58,7 @@ export async function bestandLaden(tx: Tx): Promise<Bestand> {
|
||||
.select(["position_id"])
|
||||
.where((eb) => eb.or([eb("valid_to", "is", null), eb("valid_to", ">=", heute)]))
|
||||
.execute(),
|
||||
tx.selectFrom("employees").select(["id", "personnel_number", "email", "company_email", "sv_nummer"]).execute(),
|
||||
tx.selectFrom("employees").select(["id", "personnel_number", "email", "company_email", "cornerstone_id", "sv_nummer"]).execute(),
|
||||
]);
|
||||
|
||||
const besetzt = new Set(besetzungen.map((b) => b.position_id));
|
||||
@@ -73,6 +73,7 @@ export async function bestandLaden(tx: Tx): Promise<Bestand> {
|
||||
// kann sie fehlen.
|
||||
emails: new Set(personen.filter((e) => e.email).map((e) => e.email!.toLowerCase())),
|
||||
firmenEmails: new Set(personen.filter((e) => e.company_email).map((e) => e.company_email!.toLowerCase())),
|
||||
cornerstoneIds: new Set(personen.filter((e) => e.cornerstone_id).map((e) => e.cornerstone_id!)),
|
||||
svNummern: new Set(personen.filter((e) => e.sv_nummer).map((e) => normalizeSvnr(e.sv_nummer!))),
|
||||
};
|
||||
}
|
||||
@@ -211,6 +212,7 @@ export async function laden(
|
||||
address_country: txt(w.address_country),
|
||||
email: txt(w.email)!,
|
||||
company_email: txt(w.company_email),
|
||||
cornerstone_id: txt(w.cornerstone_id),
|
||||
phone: txt(w.phone),
|
||||
title_prefix: liste(w.title_prefix) ?? [],
|
||||
title_suffix: liste(w.title_suffix) ?? [],
|
||||
|
||||
@@ -240,6 +240,14 @@ export const BLATT_PERSONEN: BlattSchema = {
|
||||
hinweis: "Dienstliche Adresse. Freiwillig, eindeutig. Geht in den Export für die Mitarbeiterbefragung.",
|
||||
beispiel: "s.aigner@manner.com",
|
||||
},
|
||||
{
|
||||
name: "Cornerstone-ID",
|
||||
ziel: "cornerstone_id",
|
||||
pflicht: false,
|
||||
typ: { art: "text" },
|
||||
hinweis: "Kennung im Lernsystem Cornerstone. Freiwillig, eindeutig. Füllt dort „User ID“ und „Username“.",
|
||||
beispiel: "10000382",
|
||||
},
|
||||
{ name: "Private Telefonnummer", ziel: "phone", pflicht: false, typ: { art: "text" }, hinweis: "", beispiel: "+43 660 1234567" },
|
||||
{ name: "Adresse", ziel: "address", pflicht: false, typ: { art: "text" }, hinweis: "", beispiel: "Hauptstraße 1" },
|
||||
{ name: "PLZ", ziel: "postal_code", pflicht: false, typ: { art: "text" }, hinweis: "", beispiel: "1010" },
|
||||
|
||||
@@ -35,6 +35,7 @@ export type Bestand = {
|
||||
personalnummern: Map<number, string>;
|
||||
emails: Set<string>;
|
||||
firmenEmails: Set<string>;
|
||||
cornerstoneIds: Set<string>;
|
||||
svNummern: Set<string>;
|
||||
};
|
||||
|
||||
@@ -46,6 +47,7 @@ export const LEERER_BESTAND: Bestand = {
|
||||
personalnummern: new Map(),
|
||||
emails: new Set(),
|
||||
firmenEmails: new Set(),
|
||||
cornerstoneIds: new Set(),
|
||||
svNummern: new Set(),
|
||||
};
|
||||
|
||||
@@ -265,6 +267,7 @@ export function pruefe(blaetter: ImportSheet[], bestand: Bestand = LEERER_BESTAN
|
||||
const personalnummern = new Set([...bestand.personalnummern.keys()]);
|
||||
const emails = new Set([...bestand.emails]);
|
||||
const firmenEmails = new Set([...bestand.firmenEmails]);
|
||||
const cornerstoneIds = new Set([...bestand.cornerstoneIds]);
|
||||
const svNummern = new Set([...bestand.svNummern]);
|
||||
const belegtePlanstellen = new Map<string, number>();
|
||||
const eintritte = new Map<number, string>();
|
||||
@@ -297,6 +300,17 @@ export function pruefe(blaetter: ImportSheet[], bestand: Bestand = LEERER_BESTAN
|
||||
}
|
||||
}
|
||||
|
||||
// Die Kennung gehört genau einer Person; die Spalte trägt einen
|
||||
// eindeutigen Index. Ohne Prüfung hier bräche erst das Schreiben ab —
|
||||
// mitten im Import und ohne Zeilennummer.
|
||||
const cornerstoneId = s(w.cornerstone_id);
|
||||
if (cornerstoneId) {
|
||||
if (cornerstoneIds.has(cornerstoneId)) {
|
||||
melde("Personen", z.zeile, "Cornerstone-ID", "Kommt bereits vor.", cornerstoneId);
|
||||
}
|
||||
cornerstoneIds.add(cornerstoneId);
|
||||
}
|
||||
|
||||
const geburt = s(w.birth_date);
|
||||
const svRoh = s(w.sv_nummer);
|
||||
if (svRoh) {
|
||||
|
||||
@@ -214,6 +214,14 @@ export type Database = {
|
||||
* das Haus verlassen. Der Honestly-Export nimmt diese hier.
|
||||
*/
|
||||
company_email: string | null;
|
||||
/**
|
||||
* Kennung der Person im Lernsystem Cornerstone (CSOD).
|
||||
*
|
||||
* Freiwillig und eindeutig. Als Text geführt — führende Nullen
|
||||
* gingen in einer numerischen Spalte verloren, und gerechnet wird
|
||||
* mit der Kennung ohnehin nicht.
|
||||
*/
|
||||
cornerstone_id: string | null;
|
||||
phone: string | null;
|
||||
job_title: string;
|
||||
location_id: string;
|
||||
@@ -294,6 +302,7 @@ export type Database = {
|
||||
address_country?: string | null;
|
||||
email?: string | null;
|
||||
company_email?: string | null;
|
||||
cornerstone_id?: string | null;
|
||||
phone?: string | null;
|
||||
job_title: string;
|
||||
location_id: string;
|
||||
|
||||
@@ -55,6 +55,10 @@ export function vorbelegungAus(employee: EmployeeRow): Partial<HireDraftData> {
|
||||
// stillschweigend. Sichtbar vorbelegt lässt sie sich bewusst ersetzen
|
||||
// oder leeren.
|
||||
companyEmail: employee.company_email ?? "",
|
||||
// Aus demselben Grund vorbelegt wie die Firmenadresse: der Assistent
|
||||
// schickt das Feld in jedem Fall mit, und leer geliefert löschte es die
|
||||
// gespeicherte Kennung stillschweigend.
|
||||
cornerstoneId: employee.cornerstone_id ?? "",
|
||||
phone: employee.phone ?? "",
|
||||
locationId: employee.location_id,
|
||||
besetzung: employee.source,
|
||||
|
||||
Reference in New Issue
Block a user