import { ABSENCE_TYPES } from "@/lib/absence"; // Was in einer Importdatei stehen darf. // // Diese Datei ist die einzige Quelle für drei Dinge, die sonst // auseinanderlaufen: die Prüfung beim Import, die Vorlage zum Herunterladen // und die Hilfetexte in der Oberfläche. Eine Spalte, die hier nicht steht, // gibt es nirgends — und eine, die hier dazukommt, taucht überall auf. // // Die Blattnamen sind zugleich die Dateinamen für den CSV-Weg: „Personen.csv" // wird als Blatt „Personen" gelesen. export type FeldArt = | { art: "text" } | { art: "datum" } | { art: "zahl" } | { art: "ganzzahl" } | { art: "janein" } | { art: "liste"; werte?: readonly string[] } | { art: "auswahl"; werte: readonly string[] }; export type Spalte = { /** Überschrift in der Datei. */ name: string; /** Feld im Datensatz, den der Lader schreibt. */ ziel: string; pflicht: boolean; typ: FeldArt; hinweis: string; beispiel: string; }; export type BlattSchema = { name: string; zweck: string; /** * Spalte, an der eine Zeile erkennbar ist. Doppelte Werte darin sind ein * Fehler — sonst überschriebe die zweite Zeile die erste, und welche * gewinnt, hinge an der Reihenfolge in der Datei. */ schluessel: string | null; spalten: Spalte[]; }; const WOCHENTAGE = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"] as const; const VERHAELTNIS = ["Ehepartner:in", "Lebenspartner:in", "Kind", "Sonstige"] as const; const EREIGNIS = [ "Eintritt", "Beförderung", "Versetzung", "Karenz", "Vertragsänderung", "Stammdatenänderung", "Austritt", "Wiedereintritt", "Reorganisation", "Gehaltsanpassung", "Rückkehr", ] as const; export const BLATT_STANDORTE: BlattSchema = { name: "Standorte", zweck: "Betriebsstätten, auf die sich Personen beziehen.", schluessel: "Bezeichnung", spalten: [ { name: "Bezeichnung", ziel: "name", pflicht: true, typ: { art: "text" }, hinweis: "Eindeutig.", beispiel: "Wien" }, { name: "Land", ziel: "country", pflicht: true, typ: { art: "text" }, hinweis: "Ausgeschrieben. Steuert unter anderem, ob eine SV-Nummer verlangt wird.", beispiel: "Österreich", }, ], }; export const BLATT_ORGANISATION: BlattSchema = { name: "Organisation", zweck: "Der Aufbau: Gesellschaft, Bereiche, Abteilungen, Teams.", schluessel: "Orgnummer", spalten: [ { name: "Orgnummer", ziel: "org_number", pflicht: true, typ: { art: "text" }, hinweis: "Eindeutig. Wird von Planstellen als Verweis benutzt.", beispiel: "10000001", }, { name: "Bezeichnung", ziel: "name", pflicht: true, typ: { art: "text" }, hinweis: "", beispiel: "Produktion" }, { name: "Art", ziel: "unit_type", pflicht: true, typ: { art: "auswahl", werte: ["Gesellschaft", "Bereich", "Abteilung", "Team"] }, hinweis: "Genau eine Zeile darf „Gesellschaft“ sein — sie ist die Wurzel.", beispiel: "Bereich", }, { name: "Übergeordnet", ziel: "parent_org_number", pflicht: false, typ: { art: "text" }, hinweis: "Orgnummer der übergeordneten Einheit. Nur bei „Gesellschaft“ leer.", beispiel: "10000000", }, { name: "Gültig ab", ziel: "valid_from", pflicht: false, typ: { art: "datum" }, hinweis: "Leer = heute.", beispiel: "01.01.2020", }, { name: "Gültig bis", ziel: "valid_to", pflicht: false, typ: { art: "datum" }, hinweis: "Leer = unbefristet.", beispiel: "", }, ], }; export const BLATT_JOBKATALOG: BlattSchema = { name: "Jobkatalog", zweck: "Die Tätigkeiten, auf die Planstellen verweisen.", schluessel: "Jobcode", spalten: [ { name: "Jobcode", ziel: "code", pflicht: true, typ: { art: "text" }, hinweis: "Eindeutig.", beispiel: "50000123" }, { name: "Bezeichnung", ziel: "title", pflicht: true, typ: { art: "text" }, hinweis: "", beispiel: "Maschinenführer:in", }, ], }; export const BLATT_PLANSTELLEN: BlattSchema = { name: "Planstellen", zweck: "Die Stellen selbst — unabhängig davon, wer sie besetzt.", schluessel: "Planstellennummer", spalten: [ { name: "Planstellennummer", ziel: "position_number", pflicht: true, typ: { art: "text" }, hinweis: "Eindeutig. Personen verweisen darauf.", beispiel: "60000124", }, { name: "Orgnummer", ziel: "org_number", pflicht: true, typ: { art: "text" }, hinweis: "Muss im Blatt „Organisation“ oder bereits im System stehen.", beispiel: "10000001", }, { name: "Jobcode", ziel: "job_code", pflicht: true, typ: { art: "text" }, hinweis: "Muss im Blatt „Jobkatalog“ oder bereits im System stehen.", beispiel: "50000123", }, { name: "Leitung", ziel: "is_chief", pflicht: false, typ: { art: "janein" }, hinweis: "Ja = Leitungsstelle der Einheit. Höchstens eine je Einheit.", beispiel: "nein", }, { name: "Gültig ab", ziel: "valid_from", pflicht: false, typ: { art: "datum" }, hinweis: "Leer = heute.", beispiel: "01.01.2020" }, { name: "Gültig bis", ziel: "valid_to", pflicht: false, typ: { art: "datum" }, hinweis: "", beispiel: "" }, ], }; export const BLATT_PERSONEN: BlattSchema = { name: "Personen", zweck: "Stammdaten, Vertrag und die Planstelle, auf der die Person sitzt.", schluessel: "Personalnummer", spalten: [ { name: "Personalnummer", ziel: "personnel_number", pflicht: true, typ: { art: "ganzzahl" }, hinweis: "Eindeutig. Historie und Angehörige verweisen darauf.", beispiel: "2219", }, { name: "Vorname", ziel: "first_name", pflicht: true, typ: { art: "text" }, hinweis: "", beispiel: "Sabine" }, { name: "Nachname", ziel: "last_name", pflicht: true, typ: { art: "text" }, hinweis: "", beispiel: "Aigner" }, { name: "Geschlecht", ziel: "gender", pflicht: true, typ: { art: "auswahl", werte: ["m", "w"] }, hinweis: "Wird für die SV-Nummer und die Anrede gebraucht.", beispiel: "w", }, { name: "Geburtsdatum", ziel: "birth_date", pflicht: true, typ: { art: "datum" }, hinweis: "", beispiel: "15.08.1968" }, { name: "SV-Nummer", ziel: "sv_nummer", pflicht: false, typ: { art: "text" }, hinweis: "Zehnstellig. Prüfziffer und Geburtsdatum müssen zusammenpassen.", beispiel: "7960 150868", }, { name: "Staatsbürgerschaft", ziel: "nationality", pflicht: false, typ: { art: "text" }, hinweis: "Leer = Österreich.", beispiel: "Österreich", }, { name: "E-Mail", ziel: "email", pflicht: true, typ: { art: "text" }, hinweis: "Eindeutig.", beispiel: "s.aigner@example.at" }, { name: "Telefon", 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" }, { name: "Ort", ziel: "city", pflicht: false, typ: { art: "text" }, hinweis: "", beispiel: "Wien" }, { name: "Land", ziel: "address_country", pflicht: false, typ: { art: "text" }, hinweis: "", beispiel: "Österreich" }, { name: "Titel vorangestellt", ziel: "title_prefix", pflicht: false, typ: { art: "liste" }, hinweis: "Mehrere mit Semikolon.", beispiel: "Mag.", }, { name: "Titel nachgestellt", ziel: "title_suffix", pflicht: false, typ: { art: "liste" }, hinweis: "", beispiel: "MSc" }, { name: "Tätigkeit", ziel: "job_title", pflicht: true, typ: { art: "text" }, hinweis: "Die Bezeichnung der Person; kann von der Planstelle abweichen.", beispiel: "Projektingenieur:in", }, { name: "Standort", ziel: "location", pflicht: true, typ: { art: "text" }, hinweis: "Muss im Blatt „Standorte“ oder bereits im System stehen.", beispiel: "Wien", }, { name: "Planstellennummer", ziel: "position_number", pflicht: true, typ: { art: "text" }, hinweis: "Muss im Blatt „Planstellen“ oder bereits im System stehen und frei sein.", beispiel: "60000124", }, { name: "Eintritt", ziel: "entry_date", pflicht: true, typ: { art: "datum" }, hinweis: "", beispiel: "01.03.2015" }, { name: "Austritt", ziel: "exit_date", pflicht: false, typ: { art: "datum" }, hinweis: "Leer = weiterhin beschäftigt. Muss nach dem Eintritt liegen.", beispiel: "", }, { name: "Austrittsgrund", ziel: "exit_reason", pflicht: false, typ: { art: "text" }, hinweis: "Pflicht, wenn ein Austritt steht.", beispiel: "" }, { name: "Beschäftigung", ziel: "employment_type", pflicht: false, typ: { art: "auswahl", werte: ["Vollzeit", "Teilzeit"] }, hinweis: "Leer = Vollzeit.", beispiel: "Vollzeit", }, { name: "Wochenstunden", ziel: "weekly_hours", pflicht: false, typ: { art: "zahl" }, hinweis: "Leer = 38,5.", beispiel: "38,5" }, { name: "Arbeitstage", ziel: "work_days", pflicht: false, typ: { art: "liste", werte: WOCHENTAGE }, hinweis: "Leer = Mo;Di;Mi;Do;Fr.", beispiel: "Mo;Di;Mi;Do;Fr", }, { name: "Vertragsart", ziel: "contract_type", pflicht: false, typ: { art: "auswahl", werte: ["unbefristet", "befristet"] }, hinweis: "Leer = unbefristet.", beispiel: "unbefristet", }, { name: "Befristet bis", ziel: "contract_end_date", pflicht: false, typ: { art: "datum" }, hinweis: "Pflicht bei „befristet“, sonst leer.", beispiel: "", }, { name: "Verwendungsgruppe", ziel: "paygrade", pflicht: false, typ: { art: "auswahl", werte: ["A", "B", "C", "D", "E", "F"] }, hinweis: "Leer = B.", beispiel: "C", }, { name: "Kollektivvertrag", ziel: "collective_agreement", pflicht: false, typ: { art: "auswahl", werte: ["Handel", "Süßwaren"] }, hinweis: "Leer = Handel.", beispiel: "Handel", }, { name: "Beschäftigtengruppe", ziel: "worker_type", pflicht: false, typ: { art: "auswahl", werte: ["Angestellte:r", "Arbeiter:in"] }, hinweis: "Leer = Angestellte:r.", beispiel: "Angestellte:r", }, { name: "Monatsgehalt brutto", ziel: "monthly_salary_gross", pflicht: false, typ: { art: "zahl" }, hinweis: "", beispiel: "3450,00" }, { name: "Herkunft", ziel: "source", pflicht: false, typ: { art: "auswahl", werte: ["Intern", "Extern"] }, hinweis: "Leer = Extern.", beispiel: "Extern", }, { name: "Betriebsrat", ziel: "is_betriebsrat", pflicht: false, typ: { art: "janein" }, hinweis: "Leer = nein.", beispiel: "nein" }, { name: "Dienstwagen", ziel: "has_dienstwagen", pflicht: false, typ: { art: "janein" }, hinweis: "", beispiel: "nein" }, { name: "Laterale Führung", ziel: "is_laterale_fuehrung", pflicht: false, typ: { art: "janein" }, hinweis: "", beispiel: "nein" }, { name: "C-Level", ziel: "is_c_level", pflicht: false, typ: { art: "janein" }, hinweis: "", beispiel: "nein" }, { name: "Abwesenheit ab", ziel: "karenz_start_date", pflicht: false, typ: { art: "datum" }, hinweis: "Beginn einer Langzeitabwesenheit.", beispiel: "", }, { name: "Rückkehr geplant", ziel: "karenz_return_date", pflicht: false, typ: { art: "datum" }, hinweis: "Pflicht, wenn „Abwesenheit ab“ steht.", beispiel: "", }, { name: "Abwesenheitsart", ziel: "absence_type", pflicht: false, typ: { art: "auswahl", werte: ABSENCE_TYPES }, hinweis: "Pflicht, wenn „Abwesenheit ab“ steht.", beispiel: "", }, ], }; export const BLATT_HISTORIE: BlattSchema = { name: "Historie", zweck: "Ereignisse je Person. Alles, was vor dem Eintritt liegt, wird abgewiesen.", schluessel: null, spalten: [ { name: "Personalnummer", ziel: "personnel_number", pflicht: true, typ: { art: "ganzzahl" }, hinweis: "Muss im Blatt „Personen“ oder bereits im System stehen.", beispiel: "2219", }, { name: "Datum", ziel: "event_date", pflicht: true, typ: { art: "datum" }, hinweis: "", beispiel: "01.03.2015" }, { name: "Ereignis", ziel: "event_type", pflicht: true, typ: { art: "auswahl", werte: EREIGNIS }, hinweis: "", beispiel: "Eintritt", }, { name: "Beschreibung", ziel: "description", pflicht: true, typ: { art: "text" }, hinweis: "", beispiel: "Eintritt als Projektingenieur:in" }, ], }; export const BLATT_ANGEHOERIGE: BlattSchema = { name: "Angehörige", zweck: "Angehörige je Person.", schluessel: null, spalten: [ { name: "Personalnummer", ziel: "personnel_number", pflicht: true, typ: { art: "ganzzahl" }, hinweis: "", beispiel: "2219" }, { name: "Vorname", ziel: "first_name", pflicht: true, typ: { art: "text" }, hinweis: "", beispiel: "Julian" }, { name: "Nachname", ziel: "last_name", pflicht: true, typ: { art: "text" }, hinweis: "", beispiel: "Aigner" }, { name: "Verhältnis", ziel: "relationship", pflicht: true, typ: { art: "auswahl", werte: VERHAELTNIS }, hinweis: "", beispiel: "Kind", }, { name: "Geburtsdatum", ziel: "birth_date", pflicht: true, typ: { art: "datum" }, hinweis: "", beispiel: "04.06.2014" }, { name: "SV-Nummer", ziel: "sv_nummer", pflicht: false, typ: { art: "text" }, hinweis: "", beispiel: "" }, ], }; /** * Reihenfolge = Ladereihenfolge. * * Standorte, Organisation und Jobkatalog müssen stehen, bevor Planstellen * darauf verweisen können; Personen brauchen Planstellen; Historie und * Angehörige brauchen Personen. */ export const BLAETTER: BlattSchema[] = [ BLATT_STANDORTE, BLATT_ORGANISATION, BLATT_JOBKATALOG, BLATT_PLANSTELLEN, BLATT_PERSONEN, BLATT_HISTORIE, BLATT_ANGEHOERIGE, ]; export function blattSchema(name: string): BlattSchema | undefined { const gesucht = name.trim().toLowerCase(); return BLAETTER.find((b) => b.name.toLowerCase() === gesucht); }