Der Status kommt aus den Daten, nicht aus der Spalte
Die Liste filterte ueber die Datumsspalten, beschriftete die Zeilen aber mit
employees.status. Sobald die Spalte nachhaengt, widersprechen sich die
beiden — und sie haengt regelmaessig nach: terminate_employee setzt sie nur,
wenn das Austrittsdatum nicht in der Zukunft liegt, und es gibt keinen Lauf,
der das spaeter nachzieht (Migration 20260814100000 sagt das selbst).
Beim Kunden waren beide Richtungen zu sehen. Der Filter "Ausgetreten" fand
48 Personen, von denen mehrere als "Aktiv" beschriftet waren; der Filter
"Geplant" zeigte Nichtantritte, deren Spalte laengst "Ausgetreten" trug.
StatusChip nimmt deshalb jetzt die Zeile und den Stichtag und leitet selbst
ab. Die Spalte laesst sich nicht mehr hineinreichen — die zweite Quelle ist
nicht bloss ungenutzt, es gibt sie an dieser Stelle nicht mehr.
Dazu drei Stellen, die an derselben Spalte hingen:
* Die Akte entschied mit ihr ueber die Knoepfe. An einer Person, die seit
zwei Wochen ausgetreten ist, stand "Austritt" weiter zur Verfuegung.
* Die Sortierung nach Status ordnete nach einem Wert, der nirgends auf der
Seite steht.
* Die Karte "Anstehend" zaehlte kuenftige Eintritte und Rueckkehren ueber
die Spalte und damit anders als die Liste, auf die sie verlinkt.
Und eine Klausel, die in der Ableitung fehlte: ein Nichtantritt traegt als
Austrittsdatum den Eintrittstag. Liegt der in der Zukunft, ist auch der
Austritt groesser als der Stichtag — die vorige Korrektur verglich nur gegen
den Stichtag und blieb damit wirkungslos. Endet ein Verhaeltnis nicht
spaeter, als es beginnt, gab es keinen Tag Beschaeftigung, zu keinem
Stichtag.
This commit is contained in:
@@ -119,8 +119,10 @@ const db = new Kysely<Schema>({
|
||||
},
|
||||
});
|
||||
|
||||
const STICHTAG = "2026-09-15";
|
||||
|
||||
const ordnung = (feld: Sortierfeld, richtung: "asc" | "desc") =>
|
||||
sortiere(db.selectFrom("employees").select("id"), feld, richtung)
|
||||
sortiere(db.selectFrom("employees").select("id"), feld, richtung, STICHTAG)
|
||||
.compile()
|
||||
.sql.replace(/^.*?order by /s, "")
|
||||
.replace(/\s+/g, " ");
|
||||
@@ -222,9 +224,46 @@ describe("das erzeugte SQL", () => {
|
||||
it("setzt keinen Wert aus der Adresse in die Abfrage", () => {
|
||||
// Die Richtung ist ausgeschrieben, nicht eingesetzt. Kämen je Werte aus
|
||||
// der Adresse hierher, stünden sie im SQL statt als Parameter.
|
||||
//
|
||||
// Gebunden wird genau ein Wert, und er kommt nicht aus der Adresse: der
|
||||
// Stichtag der Statusableitung. Deshalb wird er hier namentlich
|
||||
// zugelassen und alles andere ausgeschlossen — „gar keine Parameter"
|
||||
// wäre die schärfere Zusicherung, aber die falsche.
|
||||
for (const f of SORTIERFELDER) {
|
||||
const { parameters } = sortiere(db.selectFrom("employees").select("id"), f.value, "desc").compile();
|
||||
expect(parameters, f.value).toEqual([]);
|
||||
const { parameters } = sortiere(db.selectFrom("employees").select("id"), f.value, "desc", STICHTAG).compile();
|
||||
expect(new Set(parameters), f.value).toEqual(new Set(f.value === "status" ? [STICHTAG] : []));
|
||||
}
|
||||
});
|
||||
|
||||
// ── Status: abgeleitet, nicht aus der Spalte gelesen ──────────────────
|
||||
//
|
||||
// Die Zeile zeigt den zum Stichtag abgeleiteten Status. Nach
|
||||
// `employees.status` zu sortieren hiesse, nach einem Wert zu ordnen, der
|
||||
// nirgends auf der Seite steht — eine als „Ausgetreten" beschriftete Person
|
||||
// stünde mitten unter den aktiven.
|
||||
describe("Status", () => {
|
||||
it("ordnet nach der Ableitung und nicht nach der Spalte", () => {
|
||||
const sql = ordnung("status", "asc");
|
||||
expect(sql).toContain("exit_date");
|
||||
expect(sql).toContain("entry_date");
|
||||
expect(sql).toContain("karenz_start_date");
|
||||
expect(sql).not.toContain('"status"');
|
||||
});
|
||||
|
||||
it("hält die Reihenfolge des Dienstverhältnisses ein", () => {
|
||||
// Aktiv (1), Karenz (2), Geplant (3), Ausgetreten (4) — dieselbe
|
||||
// Folge wie im Aufzählungstyp, und aussagekräftiger als alphabetisch.
|
||||
const sql = ordnung("status", "asc");
|
||||
expect(sql.indexOf("then 4")).toBeLessThan(sql.indexOf("then 3"));
|
||||
expect(sql.indexOf("then 3")).toBeLessThan(sql.indexOf("then 2"));
|
||||
expect(sql).toContain("else 1");
|
||||
});
|
||||
|
||||
it("erkennt den Nichtantritt wie die Ableitung", () => {
|
||||
// exit_date <= entry_date: kein einziger Tag Beschäftigung. Fehlte der
|
||||
// Vergleich, sortierte ein künftiger Nichtantritt unter „Geplant",
|
||||
// während sein Chip „Ausgetreten" zeigt.
|
||||
expect(ordnung("status", "asc")).toContain("exit_date <= entry_date");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user