Files
Laufzettel/docs/issues/011-mitarbeiter-abteilungen-geraete.md
florian.wilde f85bc87324
Prüfung / pruefung (push) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s
feat(stammdaten): Mitarbeiter, Abteilungen und Geraete (#25)
2026-09-25 10:52:44 +00:00

5.7 KiB
Raw Permalink Blame History

#011 M6 – Mitarbeiter, Abteilungen, Geräte

Status: erledigt Meilenstein: v0.1.0 Labels: phase-1, backend, frontend Geschätzt: 9 h Tatsächlich: 2 h 15 min

Ziel

Die Stammdaten, an denen die Historie hängt. Mitarbeiter und Geräte werden nie gelöscht, damit archivierte Läufe für immer auf sie zeigen können.

Aufgaben

  • Mitarbeiterliste: Suche über Anzeigename, Mail, UPN und sam, Filter nach Abteilung und Aktiv-Status
  • Mitarbeitersuche als wiederverwendbare Komponente: standardmäßig nur aktive, Umschalter „auch deaktivierte“ fürs Offboarding
  • Mitarbeiterseite: Stammdaten, Abteilung, Vorgesetzter, seine Geräte, alle Läufe chronologisch (Onboarding, Übergaben, Offboarding)
  • Mitarbeiter manuell anlegen und bearbeiten (herkunft = MANUELL); synchronisierte Felder sind bei herkunft = ABGLEICH gesperrt
  • Deaktivieren statt löschen (aktiv = false)
  • Abteilungen: Name (eindeutig je Kunde), Ziel-OU, Standardgruppen (String[]), Mail-Domain, Notizen
  • Geräte: Stammdaten nach Vorgabe, Pflichtregel „hostname oder bezeichnung muss gesetzt sein“, Besitzer optional
  • Geräteliste mit Suche über Hostname, Bezeichnung, Seriennummer und tagCode, Filter nach Typ
  • CSV-Import für Geräte (hostname, label, serialNumber, inventoryNumber, type, model), tagCode wird beim Import erzeugt; eigener src/lib/csv.ts
  • Archivieren statt Löschen, sobald Läufe an einem Gerät oder einer Abteilung hängen
  • Screenshots Mitarbeiterliste, Mitarbeiterseite, Geräteliste, Abteilungen in docs/screenshots/m6/

Akzeptanzkriterien

  • Test: Mitarbeitersuche liefert standardmäßig nur aktiv = true; mit Umschalter auch deaktivierte
  • Test: ein Gerät ohne hostname und ohne bezeichnung wird abgelehnt
  • Test: ein Gerät mit Läufen lässt sich nicht löschen, nur archivieren
  • Test: tagCode eines bestehenden Geräts lässt sich nicht ändern
  • Test: CSV-Import erzeugt je Zeile einen tagCode, meldet fehlerhafte Zeilen einzeln und bricht nicht ab
  • Test: bei herkunft = ABGLEICH lehnt der Service Änderungen an synchronisierten Feldern ab

Beim Bauen aufgefallen

  • Der CSV-Import hat Zeilen still verloren und Erfolg gemeldet. Ein Anführungszeichen, das in einer Zelle beginnt und nicht schließt, verschluckte alle Folgezeilen bis zum nächsten " — der Import sagte „3 von 3 Zeilen angelegt“, zwei Geräte fehlten, und in einer Bezeichnung stand der Text der verschluckten Zeilen. Umgekehrt starb der ganze Import an einer Datei, in der nirgends mehr ein " folgte. Beides ist genau das Gegenteil des Akzeptanzkriteriums. Der Zerleger setzt jetzt am Zeilenende neu auf: ein Wert reicht standardmäßig nicht über die Zeile hinaus. Das Format erlaubt es, für Hostnamen und Seriennummern ist ein Umbruch aber praktisch immer ein vergessenes Anführungszeichen — und mit dieser Grenze endet der Schaden an der Zeile, in der er beginnt. Wer eine selbst erzeugte Datei zurückliest, schaltet werteUeberZeilen ein.
  • ungepflegteAbteilungen kannte die Kundengrenze nicht. Gruppiert wurde nach dem Namen allein, also galt „Vertrieb“ als gepflegt, sobald irgendein Kunde eine Abteilung dieses Namens hatte. Beim Kunden ohne sie blieben {{ou}} und {{gruppen}} im Lauf leer, ohne dass die Seite es je sagte. Die Funktion direkt darüber machte es seit jeher richtig — zwei Funktionen im selben Modul, die sich widersprachen.
  • Die Besitzerauswahl bot Personen fremder Kunden an. Die Liste wurde einmal für die ganze Seite geholt und in jede Karte gegeben. Der Dienst wies die Wahl ab — aber erst nach dem Klick, und die Oberfläche hatte etwas angeboten, das sie nicht einlösen konnte.
  • Ein Techniker konnte ein Gerät endgültig löschen. Abteilungen und Mitarbeiter haben gar keinen Löschweg, Geräte schon — und der Tag-Code ist danach für immer verbrannt. Löschen verlangt jetzt verwaltung; die Ausnahme steht ausdrücklich in CLAUDE.md.
  • Derselbe Kunde wurde zweimal verschieden dargestellt. Die Mitarbeiterliste blendete die eigene Organisation immer aus, die Geräteliste zeigte sie immer an. Im Modus Dienstleistung hieß „keine Kundenangabe“ damit nicht „kein Kunde“, sondern „ausgerechnet dieser eine“. Jetzt liefern beide Lesemodelle den Namen, und die Seite entscheidet anhand des Betriebsmodus, ob sie ihn zeigt.
  • Ein Kommentar hat wieder eine Zusage gemacht, die der Code nicht hielt („zwei verschiedene Gründe, aber nicht dieselbe Meldung“) — gerendert wurde nur eine, und wer die Rolle nicht hatte, sah gesperrte Felder ohne jede Erklärung. Vierter Meilenstein in Folge mit genau dieser Sorte Fehler.
  • FELD stand neunmal wortgleich in neun Dateien. Jetzt einmal in src/lib/formular.ts.
  • Die E2E-Tests haben ihre Daten liegen gelassen. Sie können nichts löschen — die Anwendung kennt bewusst keinen Löschweg für Personen und Abteilungen —, also räumen sie am Ende über die Datenbank auf. Ohne das sähe jede Datenbank, gegen die sie laufen, nach ein paar Durchläufen aus wie ein Messie-Keller.
  • Die Mitarbeitersuche ist ein eigenes Bauteil (src/components/mitarbeiter-suche.tsx), weil #013 sie beim Starten eines Laufs und #014 beim Zuweisen eines Geräts wieder braucht.

Offen geblieben

  • Ab 501 aktiven Personen lässt sich ein Besitzer nicht mehr über das Auswahlfeld zuordnen. Die Grenze schützt davor, ein Verzeichnis mit zehntausend Personen in ein <select> zu gießen; die Zuweisung über die Geräteseite mit Suche kommt mit #014. Bis dahin sagt das Formular es ausdrücklich, statt einen Weg zu versprechen, den es nicht gibt.