Rauchtest: der Lebenszyklus, einmal wirklich ausgefuehrt -- und die fuenfte Fundstelle
Some checks failed
CI / Migrationen auf leerer Datenbank (push) Has been cancelled
CI / Lint, Typen, Tests, Build (push) Has been cancelled

rehire_employee war seit dem 17.09. bei jedem Aufruf kaputt, und keine Pruefung
konnte das bemerken: die Selbstpruefungen der Migrationen lesen den Text der
Funktionen, die Unit-Tests laufen ohne Datenbank, und die Integrationstests
haben keinen Bestand, gegen den sie liefen. db/tests/rauchtest.sql schliesst
die Luecke -- es ruft die Funktionen auf, gegen die echte Datenbank, in der
Reihenfolge des Lebenszyklus: anlegen, versetzen, befoerdern, vormerken,
austreten, wiedereintreten.

Zwei Eigenschaften, ohne die es gefaehrlich waere. Es laeuft als
Anwendungsrolle statt als Superuser -- sonst bewiese es nur, dass die
Funktionen fuer niemanden gehen, der sie benutzt. Und es rollt am Ende zurueck,
mit einer Zaehlung danach, die das belegt: beim Test vom 29.09. sind reale
Personen auf Testplanstellen umgezogen und dort geblieben.

Beim Schreiben fiel die fuenfte Stelle mit dem Paar aus Schliessen und
Einfuegen auf: terminate_employee. Wer heute eingestellt und heute wieder
ausgetragen wird -- ohne den Grund "No Show" --, lief in chk_assignment_range.
Die No-Show-Haelfte derselben Funktion macht es laengst richtig und erklaert
auch, warum; es galt nur fuer genau einen Austrittsgrund.
This commit is contained in:
2026-09-29 19:17:33 +02:00
parent 89ba34c901
commit 194b6d8916
2 changed files with 261 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
-- Austritt am Tag, an dem die Besetzung begann
--
-- Die fünfte Stelle mit demselben Paar aus Schliessen und Einfügen, gefunden
-- beim Schreiben des Rauchtests: terminate_employee schliesst die Besetzung auf
-- das Austrittsdatum. Wer heute eingestellt und heute wieder ausgetragen wird —
-- ohne den Grund „No Show" —, läuft damit in chk_assignment_range.
--
-- Die No-Show-Hälfte derselben Funktion macht es längst richtig und erklärt
-- auch, warum: eine Besetzung von null Tagen hat nicht stattgefunden, also wird
-- sie entfernt statt geschlossen. Nur galt das bisher für genau einen
-- Austrittsgrund. Ein Eintritt am selben Tag zurückgenommen, aber mit
-- „Einvernehmliche Auflösung" statt „No Show", scheiterte an der rohen
-- Datenbankmeldung.
--
-- Damit sind es fünf: hire/rehire brauchen es nicht (sie legen an, sie
-- schliessen nicht), transfer_employee, promote_employee und die beiden Zweige
-- des Nachtlaufs stehen seit 20260929180000, terminate_employee kommt hier
-- dazu.
do $migration$
declare
v_alt constant text := $anker$update position_assignments set valid_to = v_exit$anker$;
v_neu constant text := $anker$delete from position_assignments
where employee_id = v_employee_id and valid_to is null and valid_from >= v_exit;
update position_assignments set valid_to = v_exit$anker$;
v_def text;
v_anzahl int;
begin
select pg_get_functiondef(p.oid) into v_def
from pg_proc p join pg_namespace n on n.oid = p.pronamespace
where n.nspname = 'public' and p.proname = 'terminate_employee' and p.prokind = 'f';
if v_def is null then raise exception 'terminate_employee ist nicht vorhanden.'; end if;
v_anzahl := (length(v_def) - length(replace(v_def, v_alt, ''))) / length(v_alt);
if v_anzahl <> 1 then
raise exception 'Der Anker in terminate_employee kommt % mal vor, erwartet einmal.', v_anzahl;
end if;
execute replace(v_def, v_alt, v_neu);
end
$migration$;
-- Selbstprüfung: das Neue und alles, was an dieser Funktion schon einmal
-- verlorengegangen ist. Die Anmerkung ist beim Umbau auf No-Show einmal
-- stillschweigend verschwunden und fiel erst durch eine Frage des Kunden auf.
do $$
declare
v_def text;
begin
select pg_get_functiondef(p.oid) into v_def
from pg_proc p join pg_namespace n on n.oid = p.pronamespace
where n.nspname = 'public' and p.proname = 'terminate_employee' and p.prokind = 'f';
if v_def not like '%valid_from >= v_exit%' then
raise exception 'terminate_employee raeumt die Besetzung vom selben Tag nicht ab.';
end if;
if v_def not like '%No Show%' then
raise exception 'terminate_employee kennt den Nichtantritt nicht mehr.';
end if;
if v_def not like '%v_note%' then
raise exception 'terminate_employee schreibt die Anmerkung nicht.';
end if;
if v_def not like '%austrittsart%' then
raise exception 'terminate_employee schreibt die Austrittsart nicht.';
end if;
if v_def not like '%require_hr_admin()%' then
raise exception 'terminate_employee prueft die Rechte nicht.';
end if;
if v_def not like '%search_path%' then
raise exception 'terminate_employee hat keinen festen search_path.';
end if;
raise notice 'terminate_employee: Austritt am selben Tag abgeraeumt.';
end
$$;