Anmerkungen vom 16.09.: Uebersicht gegliedert, Personalnummer prueft frueher

1) Die Kacheln stehen jetzt in drei Gruppen — Personalstand,
Personalbewegung, Recruiting & Vakanzen — in der Reihenfolge aus dem Entwurf
des Kunden. Acht Zahlen nebeneinander sind acht Zahlen; sie beantworten aber
drei verschiedene Fragen, und ohne Ueberschrift muss man jede Beschriftung
einzeln lesen, um das herauszufinden. "Aktives Dienstverhaeltnis" steht
vorn: es ist die Bezugsgroesse fast jeder Personalkennzahl.

2) Der Namensfilter in "Anstehend" ist jetzt immer da. Die Schwelle "erst ab
neun Eintraegen" war in der Bedienung falsch — das Feld erschien bei 180
Tagen und verschwand bei 30, und ein Bedienelement, das je nach Zeitraum da
ist oder nicht, wirkt wie ein Fehler.

3b) Der Filter heisst jetzt "Aktives Dienstverhaeltnis (Aktiv +
Langzeitabwesenheit)" — derselbe Name wie die Kachel, die dorthin verlinkt.

6) Die Personalnummer wird gegen die Datenbank geprueft, waehrend sie
eingetippt wird, und nennt bei einem Treffer die Person, die sie schon hat.
hire_employee weist sie weiterhin ab — das bleibt die verbindliche Pruefung,
denn zwischen Frage und Anlegen kann jemand anderes dieselbe Nummer
vergeben. Nur kam diese Abweisung bisher nach sechs Schritten Eingabe, und
das Feld steht im ersten Schritt.

Gemerkt wird dabei die gepruefte *Nummer* samt Ergebnis, nicht ein Ja/Nein:
so ist die Sperre eine Ableitung aus dem, was im Feld steht, und es gibt
keinen Zustand, dessen Zuruecksetzen man vergessen koennte.

Zu 4) geprueft, nichts geaendert: die FTE-Kachel rechnet bereits Summe der
Wochenstunden der heute Aktiven durch 38,5. Der Berichtemanager rechnet
dieselbe Formel, nur als Summe der Einzelquotienten geschrieben.
This commit is contained in:
2026-09-16 22:23:04 +02:00
parent 4dc27bf212
commit 9ad2954970
7 changed files with 266 additions and 75 deletions

View File

@@ -15,6 +15,44 @@ async function callRpc(fn: MutationFn, payload: Record<string, unknown>, revalid
return result;
}
/**
* Ist diese Personalnummer noch frei?
*
* ── Warum das trotz der Prüfung in der Datenbank hier steht ──────────
*
* `hire_employee` weist eine vergebene Nummer ab, und das bleibt die
* verbindliche Prüfung: zwischen dieser Frage und dem Anlegen können Sekunden
* liegen, und in denen kann jemand anderes dieselbe Nummer vergeben. Der
* Unique-Index ist die einzige Stelle, die das sicher ausschliesst.
*
* Nur kommt diese Abweisung ganz am Ende — nach Position, Vertrag,
* Angehörigen, Notfallkontakt, sechs Schritten Eingabe. Die Nummer steht im
* *ersten* Feld des *ersten* Schritts. Wer sie vertippt, erfährt es
* frühestens nach fünf Minuten und darf dann suchen, welche der Angaben
* gemeint war.
*
* Deshalb hier die frühe Auskunft und dort die Entscheidung. Es ist keine
* doppelte Wahrheit, sondern dieselbe Frage zu zwei Zeitpunkten — und wenn
* die späte Antwort einmal abweicht, gewinnt sie.
*
* Kein `ActionResult`: eine vergebene Nummer ist kein Fehler des Aufrufs,
* sondern die Antwort auf die Frage.
*/
export async function personalnummerVergeben(nummer: number): Promise<{ vergeben: boolean; name?: string }> {
if (!Number.isInteger(nummer) || nummer <= 0) return { vergeben: false };
return withUser(await currentUserId(), async (tx) => {
const treffer = await tx
.selectFrom("employees")
.select(["first_name", "last_name"])
.where("personnel_number", "=", nummer)
.executeTakeFirst();
// Der Name wird mitgegeben, weil „bereits vergeben" allein die Frage
// aufwirft, an wen — und die Antwort ist meistens der Grund: dieselbe
// Person ist schon angelegt, oder es war ein Zahlendreher.
return treffer ? { vergeben: true, name: `${treffer.first_name} ${treffer.last_name}` } : { vergeben: false };
});
}
export async function hireEmployee(payload: {
/**
* Wird eingegeben, nicht vergeben.