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.
768 lines
29 KiB
TypeScript
768 lines
29 KiB
TypeScript
// Von Hand gepflegt, passend zu db/migrations/*.sql.
|
|
//
|
|
// Erzeugt wird hier nichts: scripts/check-schema-types.mjs haelt die Datei
|
|
// Spalte fuer Spalte gegen die Migrationen und meldet jede Abweichung.
|
|
|
|
export type EmploymentStatus = "Aktiv" | "Karenz" | "Geplant" | "Ausgetreten";
|
|
export type EmploymentType = "Vollzeit" | "Teilzeit";
|
|
export type ContractType = "unbefristet" | "befristet";
|
|
export type PaygradeType = "A" | "B" | "C" | "D" | "E" | "F";
|
|
export type SourceType = "Intern" | "Extern";
|
|
export type GenderType = "m" | "w";
|
|
/**
|
|
* Die sozialversicherungsrechtliche Beschäftigtengruppe.
|
|
*
|
|
* Lehrling steht seit September 2026 daneben (Migration 20260910140000).
|
|
* Bis dahin wurden Lehrlinge als Angestellte:r oder Arbeiter:in geführt,
|
|
* was sie nicht sind — und was jede Auswertung nach dieser Spalte um
|
|
* genau diese Personen verfälschte.
|
|
*/
|
|
export type WorkerType = "Angestellte:r" | "Arbeiter:in" | "Lehrling";
|
|
export type CollectiveAgreement = "Handel" | "Süßwaren";
|
|
export type Weekday = "Mo" | "Di" | "Mi" | "Do" | "Fr" | "Sa" | "So";
|
|
|
|
/**
|
|
* Antriebsart des Dienstwagens.
|
|
*
|
|
* Bewusst keine dritte Möglichkeit „unbekannt": die Angabe hängt per CHECK
|
|
* an has_dienstwagen, und wer einen Dienstwagen hat, weiss auch, ob er lädt
|
|
* oder tankt.
|
|
*/
|
|
export type DienstwagenArt = "Verbrenner" | "Elektro";
|
|
|
|
/**
|
|
* Gesetzlich geregelte Teilzeiten.
|
|
*
|
|
* Keine Abwesenheiten: die Person arbeitet, nur kürzer. Als Zustand geführt,
|
|
* damit sich auswerten lässt, wer gerade in einer ist — mit einem optionalen
|
|
* Enddatum, weil nicht jede ein bekanntes Ende hat.
|
|
*/
|
|
export type TeilzeitArt = "Bildungsteilzeit" | "Elternteilzeit" | "Pflegeteilzeit" | "Wiedereingliederungsteilzeit";
|
|
|
|
/**
|
|
* Auf wessen Betreiben ein Dienstverhältnis endet.
|
|
*
|
|
* Eigene Angabe und **nicht** aus der Beendigungsart abgeleitet: die in
|
|
* Österreich übliche einvernehmliche Auflösung kann von beiden Seiten
|
|
* ausgehen und sagt über den Anstoss nichts aus. Die Begründung steht
|
|
* ausführlich in lib/beendigung.ts und in Migration 20260917100000.
|
|
*/
|
|
export type Austrittsart = "freiwillig" | "unfreiwillig";
|
|
|
|
/**
|
|
* Form der Beschäftigung — zweite Achse neben `worker_type`.
|
|
*
|
|
* Kein Aufzählungstyp in der Datenbank, sondern ein CHECK auf text
|
|
* (chk_mitarbeiterart). Die Beschriftungen stehen in lib/mitarbeiterart.ts.
|
|
*/
|
|
export type Mitarbeiterart = "Standard" | "Praktikant:in" | "Geringfügige Beschäftigung" | "Altersteilzeit";
|
|
|
|
/**
|
|
* Personenkreise des besonderen Kündigungsschutzes.
|
|
*
|
|
* Kein Aufzählungstyp in der Datenbank, sondern ein CHECK auf text
|
|
* (chk_kuendigungsschutz_personenkreis): die Liste ist Rechtslage und ändert
|
|
* sich mit dem Gesetz — ein Typ liesse einen zurückgenommenen Wert für immer
|
|
* stehen. Die Beschriftungen für die Oberfläche stehen in
|
|
* lib/kuendigungsschutz.ts und müssen zur Bedingung passen.
|
|
*/
|
|
export type KuendigungsschutzGrund =
|
|
| "Eltern"
|
|
| "Schwangerschaft"
|
|
| "Karenzurlaub"
|
|
| "Familienzeit"
|
|
| "Elternteilzeit"
|
|
| "Betriebsräte & Ersatzmitglieder"
|
|
| "Jugendvertrauenspersonen"
|
|
| "Behindertenvertrauenspersonen & Stellvertreter"
|
|
| "Präsenz-, Ausbildungs- oder Zivildienst"
|
|
| "Begünstigte behinderte ArbeitnehmerInnen"
|
|
| "Familienhospizkarenz"
|
|
| "Familienhospizteilzeit";
|
|
|
|
/**
|
|
* Verhältnis zum Notfallkontakt.
|
|
*
|
|
* Auswahlliste statt Freitext, damit sich danach auswerten lässt und nicht
|
|
* „Gattin", „Ehefrau" und „Frau" nebeneinander stehen. „Sonstige" ist der
|
|
* Ausweg für alles, was hier fehlt — ohne ihn wäre die Liste eine Anmassung.
|
|
*
|
|
* In der Datenbank bleibt die Spalte `text`: eine Aufzählung dort würde jede
|
|
* Ergänzung zu einer Migration machen, und diese Liste wird sich ändern.
|
|
*/
|
|
export const EMERGENCY_RELATIONS = [
|
|
"Gattin/Gatte",
|
|
"Lebensgefährtin/Lebensgefährte",
|
|
"Mutter",
|
|
"Vater",
|
|
"Tochter",
|
|
"Sohn",
|
|
"Schwester",
|
|
"Bruder",
|
|
"Freundin/Freund",
|
|
"Sonstige",
|
|
] as const;
|
|
|
|
export type EmergencyRelation = (typeof EMERGENCY_RELATIONS)[number];
|
|
|
|
/**
|
|
* Eine einzelne Feldänderung im Protokoll.
|
|
*
|
|
* `vorher` und `nachher` sind bewusst Text: die Datenbank stellt jeden Typ
|
|
* über ::text dar, damit ein Datum, eine Zahl und eine Liste von Arbeitstagen
|
|
* in derselben Spalte nebeneinander stehen können. Für die Anzeige reicht
|
|
* das; gerechnet wird damit nicht.
|
|
*/
|
|
export type AuditChange = { feld: string; vorher: string | null; nachher: string | null };
|
|
export type RelationshipType = "Ehepartner:in" | "Lebenspartner:in" | "Kind" | "Sonstige";
|
|
export type NoteCategory = "Allgemein" | "Vertraulich" | "Personalgespräch" | "Wiedervorlage" | "Lob / Anerkennung";
|
|
// Single HR-only role (see docs/decisions/0001-hr-only-access.md). Kept as a
|
|
// union (not a string literal) so a future hr_admin/hr_user split, if ever
|
|
// technically required, is a type-level addition, not a rewrite.
|
|
export type ProfileRole = "hr";
|
|
/** Etikett einer Organisationseinheit; die Struktur steckt in parent_id. */
|
|
export type OrgUnitType = "Gesellschaft" | "Bereich" | "Abteilung" | "Team";
|
|
export type HistoryEventType =
|
|
| "Eintritt"
|
|
| "Beförderung"
|
|
| "Versetzung"
|
|
| "Karenz"
|
|
| "Vertragsänderung"
|
|
| "Stammdatenänderung"
|
|
| "Austritt"
|
|
| "Wiedereintritt"
|
|
| "Reorganisation"
|
|
| "Gehaltsanpassung"
|
|
| "Rückkehr"
|
|
// Wechsel von extern auf intern. Eigenes Ereignis auf Wunsch des Kunden —
|
|
// ein Vorgang wie Neueinstellung oder Versetzung, nicht bloss ein
|
|
// geändertes Feld. Nur in dieser Richtung (Migration 20260917110000).
|
|
| "Übernahme";
|
|
export type PendingChangeType =
|
|
| "transfer"
|
|
| "promotion"
|
|
| "karenz_start"
|
|
| "karenz_return"
|
|
| "contract_change"
|
|
| "reorg";
|
|
export type PendingChangeStatus = "pending" | "applied" | "cancelled";
|
|
|
|
export type Database = {
|
|
public: {
|
|
Tables: {
|
|
locations: {
|
|
Row: { id: string; name: string; country: string };
|
|
Insert: { id?: string; name: string; country: string };
|
|
Update: Partial<{ id: string; name: string; country: string }>;
|
|
};
|
|
profiles: {
|
|
Row: {
|
|
id: string;
|
|
email: string;
|
|
full_name: string | null;
|
|
role: ProfileRole;
|
|
is_active: boolean;
|
|
created_by: string | null;
|
|
created_at: string;
|
|
updated_at: string;
|
|
};
|
|
Insert: {
|
|
id: string;
|
|
email: string;
|
|
full_name?: string | null;
|
|
role?: ProfileRole;
|
|
is_active?: boolean;
|
|
created_by?: string | null;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
};
|
|
Update: Partial<{
|
|
id: string;
|
|
email: string;
|
|
full_name: string | null;
|
|
role: ProfileRole;
|
|
is_active: boolean;
|
|
created_by: string | null;
|
|
created_at: string;
|
|
updated_at: string;
|
|
}>;
|
|
};
|
|
employees: {
|
|
Row: {
|
|
id: string;
|
|
personnel_number: number;
|
|
first_name: string;
|
|
last_name: string;
|
|
gender: GenderType;
|
|
birth_date: string;
|
|
sv_nummer: string | null;
|
|
nationality: string;
|
|
/** Aufenthaltstitel — nur ausserhalb von EU, EWR und Schweiz erhoben. */
|
|
hat_aufenthaltstitel: boolean;
|
|
/** Gültig bis, falls befristet. Nur mit dem Kennzeichen zusammen erlaubt. */
|
|
aufenthaltstitel_bis: string | null;
|
|
address: string | null;
|
|
postal_code: string | null;
|
|
city: string | null;
|
|
address_country: string | null;
|
|
/** Private Adresse, freiwillig — eindeutig, wenn angegeben. */
|
|
email: string | null;
|
|
/**
|
|
* Dienstliche Adresse, freiwillig — eindeutig, wenn angegeben.
|
|
*
|
|
* Getrennt von `email`: die private gehört nicht in Dateien, die
|
|
* 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;
|
|
employment_type: EmploymentType;
|
|
weekly_hours: number;
|
|
/** @deprecated Salary is out of MVP scope; column kept only for pre-existing data. */
|
|
monthly_salary_gross: number | null;
|
|
contract_type: ContractType;
|
|
contract_end_date: string | null;
|
|
paygrade: PaygradeType;
|
|
source: SourceType;
|
|
status: EmploymentStatus;
|
|
entry_date: string;
|
|
exit_date: string | null;
|
|
exit_reason: string | null;
|
|
/** Freiwillig oder unfreiwillig — eigene Angabe, nur mit einem Austritt erlaubt. */
|
|
austrittsart: Austrittsart | null;
|
|
karenz_start_date: string | null;
|
|
karenz_return_date: string | null;
|
|
absence_type: string | null;
|
|
avatar_color: string | null;
|
|
worker_type: WorkerType;
|
|
/** Form der Beschäftigung, NOT NULL mit Vorgabe „Standard" — chk_mitarbeiterart. */
|
|
mitarbeiterart: Mitarbeiterart;
|
|
collective_agreement: CollectiveAgreement;
|
|
work_days: Weekday[];
|
|
is_betriebsrat: boolean;
|
|
has_dienstwagen: boolean;
|
|
/** Null genau dann, wenn kein Dienstwagen vorhanden ist — chk_dienstwagen_art. */
|
|
dienstwagen_art: DienstwagenArt | null;
|
|
/** Besonderer Kündigungsschutz — löst beim Austritt eine Warnung aus. */
|
|
has_kuendigungsschutz: boolean;
|
|
/** Ende des Schutzes, falls bekannt. Nur mit dem Kennzeichen zusammen erlaubt. */
|
|
kuendigungsschutz_bis: string | null;
|
|
/**
|
|
* Personenkreis nach dem besonderen Kündigungsschutz — chk_kuendigungsschutz_personenkreis.
|
|
* Freiwillig, denn der Altbestand trägt das Kennzeichen ohne Grund.
|
|
*/
|
|
kuendigungsschutz_grund: KuendigungsschutzGrund | null;
|
|
/** Beginn des Schutzes, falls bekannt. Nur mit dem Kennzeichen zusammen erlaubt. */
|
|
kuendigungsschutz_ab: string | null;
|
|
/** Begünstigung nach dem Behinderteneinstellungsgesetz. */
|
|
ist_beguenstigt_behindert: boolean;
|
|
/** Grad der Behinderung in Prozent laut Bescheid, 1..100 — chk_behinderung_grad. */
|
|
behinderung_grad: number | null;
|
|
/** Beginn laut Bescheid. Nur mit dem Kennzeichen zusammen erlaubt. */
|
|
behinderung_ab: string | null;
|
|
/** Ende laut Bescheid, falls befristet. Nur mit dem Kennzeichen zusammen erlaubt. */
|
|
behinderung_bis: string | null;
|
|
/** Bildungs-, Eltern-, Pflege- oder Wiedereingliederungsteilzeit; null bei einer gewöhnlichen Regelung. */
|
|
teilzeit_art: TeilzeitArt | null;
|
|
/** Ende der Teilzeit, falls bekannt. Nur mit einer Variante zusammen erlaubt. */
|
|
teilzeit_bis: string | null;
|
|
/** Nur gemeinsam gesetzt oder gemeinsam leer — chk_emergency_contact. */
|
|
emergency_contact_name: string | null;
|
|
emergency_contact_phone: string | null;
|
|
emergency_contact_relation: string | null;
|
|
is_laterale_fuehrung: boolean;
|
|
is_c_level: boolean;
|
|
title_prefix: string[];
|
|
title_suffix: string[];
|
|
created_at: string;
|
|
updated_at: string;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
gender: GenderType;
|
|
birth_date: string;
|
|
sv_nummer?: string | null;
|
|
nationality?: string;
|
|
hat_aufenthaltstitel?: boolean;
|
|
aufenthaltstitel_bis?: string | null;
|
|
address?: string | null;
|
|
postal_code?: string | null;
|
|
city?: string | null;
|
|
address_country?: string | null;
|
|
email?: string | null;
|
|
company_email?: string | null;
|
|
cornerstone_id?: string | null;
|
|
phone?: string | null;
|
|
job_title: string;
|
|
location_id: string;
|
|
employment_type?: EmploymentType;
|
|
weekly_hours?: number;
|
|
contract_type?: ContractType;
|
|
contract_end_date?: string | null;
|
|
paygrade?: PaygradeType;
|
|
source?: SourceType;
|
|
status?: EmploymentStatus;
|
|
entry_date: string;
|
|
exit_date?: string | null;
|
|
exit_reason?: string | null;
|
|
austrittsart?: Austrittsart | null;
|
|
karenz_start_date?: string | null;
|
|
karenz_return_date?: string | null;
|
|
absence_type?: string | null;
|
|
avatar_color?: string | null;
|
|
worker_type?: WorkerType;
|
|
mitarbeiterart?: Mitarbeiterart;
|
|
collective_agreement?: CollectiveAgreement;
|
|
work_days?: Weekday[];
|
|
is_betriebsrat?: boolean;
|
|
has_dienstwagen?: boolean;
|
|
dienstwagen_art?: DienstwagenArt | null;
|
|
has_kuendigungsschutz?: boolean;
|
|
kuendigungsschutz_bis?: string | null;
|
|
kuendigungsschutz_grund?: KuendigungsschutzGrund | null;
|
|
kuendigungsschutz_ab?: string | null;
|
|
ist_beguenstigt_behindert?: boolean;
|
|
behinderung_grad?: number | null;
|
|
behinderung_ab?: string | null;
|
|
behinderung_bis?: string | null;
|
|
teilzeit_art?: TeilzeitArt | null;
|
|
teilzeit_bis?: string | null;
|
|
emergency_contact_name?: string | null;
|
|
emergency_contact_phone?: string | null;
|
|
emergency_contact_relation?: string | null;
|
|
is_laterale_fuehrung?: boolean;
|
|
is_c_level?: boolean;
|
|
title_prefix?: string[];
|
|
title_suffix?: string[];
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["employees"]["Insert"]>;
|
|
};
|
|
employee_history: {
|
|
Row: {
|
|
id: string;
|
|
employee_id: string;
|
|
event_date: string;
|
|
event_type: HistoryEventType;
|
|
description: string;
|
|
/** Feldweise Änderungen — dieselbe Form wie audit_log.changes. */
|
|
changes: AuditChange[] | null;
|
|
/** Der geplante Vorgang, solange die Änderung noch nicht wirksam ist. */
|
|
pending_id: string | null;
|
|
created_at: string;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
employee_id: string;
|
|
event_date: string;
|
|
event_type: HistoryEventType;
|
|
description: string;
|
|
changes?: AuditChange[] | null;
|
|
pending_id?: string | null;
|
|
created_at?: string;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["employee_history"]["Insert"]>;
|
|
};
|
|
employee_dependents: {
|
|
Row: {
|
|
id: string;
|
|
employee_id: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
relationship: RelationshipType;
|
|
sv_nummer: string | null;
|
|
birth_date: string;
|
|
created_at: string;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
employee_id: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
relationship: RelationshipType;
|
|
sv_nummer?: string | null;
|
|
birth_date: string;
|
|
created_at?: string;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["employee_dependents"]["Insert"]>;
|
|
};
|
|
employee_notes: {
|
|
Row: {
|
|
id: string;
|
|
employee_id: string;
|
|
author_user_id: string | null;
|
|
author_name: string;
|
|
category: NoteCategory;
|
|
note_text: string;
|
|
due_date: string | null;
|
|
done: boolean;
|
|
done_at: string | null;
|
|
done_by: string | null;
|
|
created_at: string;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
employee_id: string;
|
|
author_user_id?: string | null;
|
|
author_name: string;
|
|
category?: NoteCategory;
|
|
note_text: string;
|
|
due_date?: string | null;
|
|
done?: boolean;
|
|
done_at?: string | null;
|
|
done_by?: string | null;
|
|
created_at?: string;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["employee_notes"]["Insert"]>;
|
|
};
|
|
// locked_by/locked_at: wer den Entwurf gerade offen hat. Die Regeln
|
|
// hire_drafts_update und _delete lassen nur den Halter schreiben, und
|
|
// die Sperre läuft ab (Migration 20260910160000) — sonst nähme ein
|
|
// geschlossener Reiter den Entwurf für immer mit.
|
|
hire_drafts: {
|
|
Row: {
|
|
id: string;
|
|
created_by: string | null;
|
|
step: number;
|
|
payload: Record<string, unknown>;
|
|
updated_at: string;
|
|
locked_by: string | null;
|
|
locked_at: string | null;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
created_by?: string | null;
|
|
step?: number;
|
|
payload: Record<string, unknown>;
|
|
updated_at?: string;
|
|
locked_by?: string | null;
|
|
locked_at?: string | null;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["hire_drafts"]["Insert"]>;
|
|
};
|
|
saved_reports: {
|
|
Row: { id: string; created_by: string | null; name: string; config: Record<string, unknown>; created_at: string };
|
|
Insert: { id?: string; created_by?: string | null; name: string; config: Record<string, unknown>; created_at?: string };
|
|
Update: Partial<Database["public"]["Tables"]["saved_reports"]["Insert"]>;
|
|
};
|
|
audit_log: {
|
|
Row: {
|
|
id: string;
|
|
occurred_at: string;
|
|
actor_user_id: string | null;
|
|
actor_name: string;
|
|
action: string;
|
|
target_label: string;
|
|
target_employee_id: string | null;
|
|
details: string | null;
|
|
/**
|
|
* Feldweise Änderungen. Null bei Einträgen aus der Zeit vor
|
|
* 20260803140000_audit_changes_detail.sql — dort wurden nur die
|
|
* Feldnamen behalten, nicht die Werte, und das lässt sich nicht
|
|
* nachliefern.
|
|
*/
|
|
changes: AuditChange[] | null;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
occurred_at?: string;
|
|
actor_user_id?: string | null;
|
|
actor_name: string;
|
|
action: string;
|
|
target_label: string;
|
|
target_employee_id?: string | null;
|
|
details?: string | null;
|
|
changes?: AuditChange[] | null;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["audit_log"]["Insert"]>;
|
|
};
|
|
pending_org_changes: {
|
|
Row: {
|
|
id: string;
|
|
employee_id: string;
|
|
change_type: PendingChangeType;
|
|
effective_date: string;
|
|
payload: Record<string, unknown>;
|
|
status: PendingChangeStatus;
|
|
created_by: string | null;
|
|
created_at: string;
|
|
applied_at: string | null;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
employee_id: string;
|
|
change_type: PendingChangeType;
|
|
effective_date: string;
|
|
payload: Record<string, unknown>;
|
|
status?: PendingChangeStatus;
|
|
created_by?: string | null;
|
|
created_at?: string;
|
|
applied_at?: string | null;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["pending_org_changes"]["Insert"]>;
|
|
};
|
|
// ── SAP-OM-Modell ──────────────────────────────────────────
|
|
// O: rekursiv über parent_id, unit_type ist nur ein Etikett.
|
|
org_units: {
|
|
Row: {
|
|
id: string;
|
|
org_number: string;
|
|
name: string;
|
|
parent_id: string | null;
|
|
unit_type: OrgUnitType;
|
|
valid_from: string;
|
|
valid_to: string | null;
|
|
created_at: string;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
org_number: string;
|
|
name: string;
|
|
parent_id?: string | null;
|
|
unit_type: OrgUnitType;
|
|
valid_from?: string;
|
|
valid_to?: string | null;
|
|
created_at?: string;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["org_units"]["Insert"]>;
|
|
};
|
|
// C: Katalog der Tätigkeiten.
|
|
jobs: {
|
|
Row: { id: string; code: string; title: string; created_at: string };
|
|
Insert: { id?: string; code: string; title: string; created_at?: string };
|
|
Update: Partial<Database["public"]["Tables"]["jobs"]["Insert"]>;
|
|
};
|
|
// S: Planstelle. Der Name om_positions stammt aus der Zeit, in der die
|
|
// alte positions-Tabelle noch danebenstand; sie ist inzwischen weg.
|
|
om_positions: {
|
|
Row: {
|
|
id: string;
|
|
position_number: string;
|
|
org_unit_id: string;
|
|
job_id: string;
|
|
is_chief: boolean;
|
|
valid_from: string;
|
|
valid_to: string | null;
|
|
created_at: string;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
position_number: string;
|
|
org_unit_id: string;
|
|
job_id: string;
|
|
is_chief?: boolean;
|
|
valid_from?: string;
|
|
valid_to?: string | null;
|
|
created_at?: string;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["om_positions"]["Insert"]>;
|
|
};
|
|
// Die Onboarding-Checkliste: je Person und Punkt eine Zeile. Welche
|
|
// Punkte es gibt, steht in lib/onboarding.ts — nicht hier.
|
|
onboarding_tasks: {
|
|
Row: {
|
|
id: string;
|
|
employee_id: string;
|
|
item_key: string;
|
|
erledigt: boolean;
|
|
wert: string | null;
|
|
kommentar: string | null;
|
|
created_at: string;
|
|
updated_at: string;
|
|
updated_by: string | null;
|
|
updated_by_name: string | null;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
employee_id: string;
|
|
item_key: string;
|
|
erledigt?: boolean;
|
|
wert?: string | null;
|
|
kommentar?: string | null;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
updated_by?: string | null;
|
|
updated_by_name?: string | null;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["onboarding_tasks"]["Insert"]>;
|
|
};
|
|
// Die Offboarding-Checkliste — dieselbe Form wie onboarding_tasks, für
|
|
// den anderen Weg. Punkte in lib/offboarding.ts.
|
|
offboarding_tasks: {
|
|
Row: {
|
|
id: string;
|
|
employee_id: string;
|
|
item_key: string;
|
|
erledigt: boolean;
|
|
wert: string | null;
|
|
kommentar: string | null;
|
|
created_at: string;
|
|
updated_at: string;
|
|
updated_by: string | null;
|
|
updated_by_name: string | null;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
employee_id: string;
|
|
item_key: string;
|
|
erledigt?: boolean;
|
|
wert?: string | null;
|
|
kommentar?: string | null;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
updated_by?: string | null;
|
|
updated_by_name?: string | null;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["offboarding_tasks"]["Insert"]>;
|
|
};
|
|
// Kostenstellen. Die Zuordnung hängt an der Planstelle, nicht an der
|
|
// Person: der Sitz kostet Geld, auch wenn niemand darauf sitzt.
|
|
cost_centers: {
|
|
Row: {
|
|
id: string;
|
|
code: string;
|
|
name: string;
|
|
org_unit_id: string | null;
|
|
valid_from: string;
|
|
valid_to: string | null;
|
|
created_at: string;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
code: string;
|
|
name: string;
|
|
org_unit_id?: string | null;
|
|
valid_from?: string;
|
|
valid_to?: string | null;
|
|
created_at?: string;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["cost_centers"]["Insert"]>;
|
|
};
|
|
// A011: Planstelle kontiert auf Kostenstelle, zeitabhängig.
|
|
position_cost_centers: {
|
|
Row: {
|
|
id: string;
|
|
position_id: string;
|
|
cost_center_id: string;
|
|
valid_from: string;
|
|
valid_to: string | null;
|
|
created_at: string;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
position_id: string;
|
|
cost_center_id: string;
|
|
valid_from: string;
|
|
valid_to?: string | null;
|
|
created_at?: string;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["position_cost_centers"]["Insert"]>;
|
|
};
|
|
// A008: Person besetzt Planstelle, zeitabhängig.
|
|
position_assignments: {
|
|
Row: {
|
|
id: string;
|
|
position_id: string;
|
|
employee_id: string;
|
|
valid_from: string;
|
|
valid_to: string | null;
|
|
created_at: string;
|
|
};
|
|
Insert: {
|
|
id?: string;
|
|
position_id: string;
|
|
employee_id: string;
|
|
valid_from: string;
|
|
valid_to?: string | null;
|
|
created_at?: string;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["position_assignments"]["Insert"]>;
|
|
// Beide Richtungen: über die Planstelle hängt die Verortung in der
|
|
// Organisation, über die Person die Verortung in der Akte. Die
|
|
// Einbettung erspart an einem Dutzend Stellen eine zweite Abfrage.
|
|
};
|
|
// Hinzugewählte Kolleg:innen je Person. Eine Zeile holt deren Notizen
|
|
// und Entwürfe in die Ansicht; ohne Zeile sieht man nur die eigenen.
|
|
colleague_subscriptions: {
|
|
Row: {
|
|
user_id: string;
|
|
author_user_id: string;
|
|
created_at: string;
|
|
};
|
|
Insert: {
|
|
user_id: string;
|
|
author_user_id: string;
|
|
created_at?: string;
|
|
};
|
|
Update: Partial<Database["public"]["Tables"]["colleague_subscriptions"]["Insert"]>;
|
|
};
|
|
};
|
|
Views: Record<string, never>;
|
|
Functions: {
|
|
hire_employee: { Args: { payload: Record<string, unknown> }; Returns: string };
|
|
terminate_employee: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
transfer_employee: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
promote_employee: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
start_karenz: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
adjust_karenz_return: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
record_karenz_return: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
change_employee_data: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
rehire_employee: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
add_employee_dependent: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
// Berichtigen, nicht ändern zum Stichtag: ein falscher Name war schon
|
|
// vorher falsch. Deshalb ohne `effective_date` (20260924160000).
|
|
update_employee_dependent: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
delete_employee_dependent: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
add_employee_note: { Args: { payload: Record<string, unknown> }; Returns: string };
|
|
complete_employee_note: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
// Eigenes Passwort wechseln. Die einzige mutierende Funktion **ohne**
|
|
// require_hr_admin() — sonst käme niemand aus dem erzwungenen Wechsel
|
|
// heraus, denn solange er aussteht, ist is_hr_user() false.
|
|
app_passwort_aendern: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
// Nimmt eine irrtümliche Stammdaten-/Vertragsänderung zurück. Der einzige
|
|
// Weg an der fehlenden delete-Policy auf employee_history vorbei.
|
|
delete_history_entry: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
// Berichtigt Wert und/oder Datum eines Historieneintrags.
|
|
update_history_entry: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
// Planstelle anlegen bzw. schliessen — im OM-Modell Operationen auf
|
|
// om_positions, nicht mehr auf einer eigenen Ausschreibungstabelle.
|
|
create_position: { Args: { payload: Record<string, unknown> }; Returns: string };
|
|
// Kopie einer bestehenden Planstelle — gleiche Einheit, Tätigkeit und
|
|
// Kontierung, neue Nummer, unbesetzt. Leitungsplanstellen ausgenommen.
|
|
clone_position: { Args: { payload: Record<string, unknown> }; Returns: string };
|
|
update_position: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
set_position_cost_center: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
set_onboarding_task: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
start_onboarding: { Args: { payload: Record<string, unknown> }; Returns: number };
|
|
set_offboarding_task: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
start_offboarding: { Args: { payload: Record<string, unknown> }; Returns: number };
|
|
delete_position: { Args: { payload: Record<string, unknown> }; Returns: void };
|
|
is_valid_svnr: { Args: { p_svnr: string; p_birth_date?: string | null }; Returns: boolean };
|
|
apply_due_pending_changes: { Args: Record<string, never>; Returns: number };
|
|
om_reporting_lines: {
|
|
Args: { p_as_of?: string };
|
|
Returns: {
|
|
employee_id: string;
|
|
position_id: string;
|
|
org_unit_id: string;
|
|
is_chief: boolean;
|
|
formal_manager_id: string | null;
|
|
acting_manager_id: string | null;
|
|
}[];
|
|
};
|
|
};
|
|
};
|
|
};
|