Cornerstone Report: system values, not display names
Reworked against the load spec and the 27.09. test file. The values I had guessed were the German display names, which is the first entry on the list of errors from earlier loads: Cornerstone answers "ungültiger Wert" and rejects the whole row, followed by "Alle abhängigen Felder müssen gültig sein" as a follow-on. Status Aktiv/Inaktiv -> Active/Inactive Employment Status Arbeitend/... -> Working/On Leave/Terminated User Type Mitarbeiter -> Employee Time Zone CET -> empty The time zone is the second entry on that list: only a portal time zone id is valid, an abbreviation gives "Zeitzonencode nicht eindeutig". Empty means the portal or the OU decides. Division ID is the GUID from the test file, not a name. Termination fields and Leave Reason are filled only when the employment status carries them -- a reason without a termination is an invalid state for the load, not extra information. Four fields now stay empty on purpose, because filling them would mean inventing an identifier that belongs to the target system: Location ID (locations has id/name/country and no Cornerstone id), Position ID (our S-0001 is not a Cornerstone position), Months of Service (Cornerstone derives it) and Rehired Employee (the value for "yes" is unconfirmed, and an unconfirmed value costs the whole row). Retention Rules and Organisationsstufe stay empty because the load ignores them. Header and row now match the test file byte for byte, except User ID (no TEST- prefix outside a test load), Required Training Approvals and Location ID. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,29 +21,15 @@ export async function GET(request: NextRequest) {
|
||||
const stichtag = asOf ?? todayIso();
|
||||
|
||||
const { zeilen } = await withUser(gate.userId, async (tx) => {
|
||||
const { rows, lookups, orgMaps, managerNummer } = await ladeExportMitarbeiter(tx, { asOf, filters });
|
||||
const { rows, managerNummer } = await ladeExportMitarbeiter(tx, { asOf, filters });
|
||||
|
||||
// Die beiden Angaben, die die gemeinsame Auswahl nicht mitbringt: die
|
||||
// Kostenstelle hängt an der Planstelle, der Wiedereintritt an der
|
||||
// Historie. Beide erst jetzt, weil erst jetzt feststeht, um wen es geht.
|
||||
// Die eine Angabe, die die gemeinsame Auswahl nicht mitbringt: die
|
||||
// Kostenstelle hängt an der Planstelle, nicht an der Person. Erst jetzt,
|
||||
// weil erst jetzt feststeht, um welche Planstellen es geht.
|
||||
const positionIds = [...new Set(rows.map((r) => r.position_id).filter((id): id is string => Boolean(id)))];
|
||||
const [kostenstelle, wiedereintritte] = await Promise.all([
|
||||
loadKontierungen(tx, { asOf: stichtag, positionIds }),
|
||||
tx
|
||||
.selectFrom("employee_history")
|
||||
.select("employee_id")
|
||||
.where("event_type", "=", "Wiedereintritt")
|
||||
.distinct()
|
||||
.execute(),
|
||||
]);
|
||||
|
||||
const kontext: CornerstoneKontext = {
|
||||
orgMaps,
|
||||
standortName: lookups.locationName,
|
||||
managerNummer,
|
||||
kostenstelle,
|
||||
wiedereingestellt: new Set(wiedereintritte.map((w) => w.employee_id)),
|
||||
stichtag,
|
||||
kostenstelle: await loadKontierungen(tx, { asOf: stichtag, positionIds }),
|
||||
};
|
||||
|
||||
return { zeilen: rows.map((r) => baueCornerstoneZeile(r, kontext)) };
|
||||
|
||||
Reference in New Issue
Block a user