feat(verzeichnis): LDAP-Abgleich, Zeitplan, CSV-Import und Log
Quelle anlegen, Verbindung testen, nach Zeitplan oder auf Knopfdruck abgleichen. Gelesen wird seitenweise mit searchPaginated, objectGUID kommt als Puffer und wird gemischt-endian zur GUID umsortiert. Wer im Verzeichnis verschwindet, wird hier inaktiv und nie geloescht. Drei Regeln verhindern, dass eine kaputte Eingabe wie "alle sind gegangen" aussieht: laesst sich kein einziger Eintrag zuordnen, wird niemand deaktiviert; uebersprungene Eintraege werden am dn erkannt und ausgenommen; eine von Hand angelegte Person wird uebernommen statt verdoppelt. Der Zeitplan laeuft ueber node-cron im selben Prozess, gestartet aus src/instrumentation.ts, und nimmt keine eigene Sperre - die liegt in der Datenbank, damit zwei Instanzen sich einig sind. Closes #16 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ab5777a57e
commit
16059e7846
@@ -1,6 +1,7 @@
|
||||
import Link from "next/link";
|
||||
import { Plus, User } from "lucide-react";
|
||||
import { Plus, Upload, User } from "lucide-react";
|
||||
import { MitarbeiterAnlegen } from "@/components/mitarbeiter-anlegen";
|
||||
import { MitarbeiterImportieren } from "@/components/mitarbeiter-importieren";
|
||||
import { MitarbeiterSuche } from "@/components/mitarbeiter-suche";
|
||||
import { StammdatenReiter } from "@/components/stammdaten-reiter";
|
||||
import { Herkunft } from "@/generated/prisma/enums";
|
||||
@@ -9,6 +10,7 @@ import { sitzungErforderlich } from "@/server/auth/sitzungspflicht";
|
||||
import { kundenEbeneSichtbar } from "@/server/mandant";
|
||||
import { kundenListe } from "@/server/queries/kunden";
|
||||
import { abteilungsNamen, mitarbeiterListe, type MitarbeiterZeile } from "@/server/queries/mitarbeiter";
|
||||
import { MITARBEITER_IMPORT_HOECHSTZEILEN, MITARBEITER_IMPORT_SPALTEN } from "@/server/services/mitarbeiter";
|
||||
|
||||
/**
|
||||
* Mitarbeiterliste (#011).
|
||||
@@ -138,6 +140,27 @@ export default async function MitarbeiterSeite({
|
||||
</div>
|
||||
</details>
|
||||
) : null}
|
||||
|
||||
{darfBearbeiten ? (
|
||||
/*
|
||||
* Der CSV-Import steht neben dem Formular und verlangt dasselbe Recht
|
||||
* (#016): wer eine Person eintragen darf, darf auch zwanzig auf einmal
|
||||
* eintragen. Zugeklappt, weil die tägliche Arbeit die Liste ist.
|
||||
*/
|
||||
<details className="mt-4 rounded-karte border border-linie bg-flaeche">
|
||||
<summary className="flex min-h-11 cursor-pointer list-none items-center gap-2 px-5 text-sm text-nebentext hover:text-text">
|
||||
<Upload className="size-4 text-akzent" strokeWidth={2} aria-hidden="true" />
|
||||
Personen aus einer CSV-Datei einlesen
|
||||
</summary>
|
||||
<div className="px-5 pb-5">
|
||||
<MitarbeiterImportieren
|
||||
hoechstZeilen={MITARBEITER_IMPORT_HOECHSTZEILEN}
|
||||
spalten={Object.values(MITARBEITER_IMPORT_SPALTEN).map((namen) => namen[0])}
|
||||
kunden={kunden.map(({ id, name }) => ({ id, name }))}
|
||||
/>
|
||||
</div>
|
||||
</details>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user