import { beforeEach, describe, expect, it } from "vitest"; import { Betriebsmodus, Herkunft } from "@/generated/prisma/enums"; import { abteilungAnlegen } from "@/server/services/abteilungen"; import { ungepflegteAbteilungen } from "@/server/queries/abteilungen"; import { datenbankLeeren, datenbankVerfuegbar, testPrisma } from "./helpers/db"; /** * Abteilungsvorschläge (#016). * * Die Liste, aus der ein Administrator mit einem Klick echte `Abteilung`-Einträge * macht. Jeder Eintrag ist damit ein Versprechen: der Klick muss gelingen. * Deshalb steht hier nichts, was `abteilungAnlegen` danach abweisen würde — keine * bereits (auch archiviert) gepflegte Abteilung und kein archivierter Kunde. */ async function grundbestand(modus: Betriebsmodus = Betriebsmodus.INTERN) { const eigene = await testPrisma.kunde.create({ data: { name: "Eigene Organisation", kuerzel: "EIGEN", istEigeneOrganisation: true }, }); await testPrisma.einstellung.create({ data: { id: "global", modus } }); const benutzer = await testPrisma.benutzer.create({ data: { email: "admin@firma.example", name: "Administrator", rolle: "ADMIN" }, }); return { eigene, admin: { id: benutzer.id, rolle: benutzer.rolle } }; } async function person( kundeId: string, abteilung: string, weiteres: { aktiv?: boolean; herkunft?: Herkunft } = {}, ) { const nummer = await testPrisma.mitarbeiter.count(); return testPrisma.mitarbeiter.create({ data: { kundeId, vorname: "Person", nachname: `Nummer ${nummer}`, anzeigename: `Person Nummer ${nummer}`, abteilung, ...weiteres, }, }); } describe.runIf(datenbankVerfuegbar)("Abteilungsvorschläge", () => { beforeEach(async () => { await datenbankLeeren(); delete process.env["OIDC_CUSTOMER_GROUP_PREFIX"]; }); it("zeigt nur Namen, zu denen es noch keine Abteilung gibt", async () => { const { admin, eigene } = await grundbestand(); await abteilungAnlegen({ name: "Buchhaltung", zielOu: "OU=Buchhaltung" }, admin); await person(eigene.id, "Buchhaltung"); await person(eigene.id, "Vertrieb", { herkunft: Herkunft.ABGLEICH }); await person(eigene.id, "Vertrieb"); expect(await ungepflegteAbteilungen(admin)).toEqual([ { name: "Vertrieb", anzahl: 2, kundeId: eigene.id }, ]); }); it("zählt deaktivierte Personen nicht mit", async () => { // Eine Abteilung, in der nur noch Ausgeschiedene stehen, braucht keine // Ziel-OU mehr — und ein Vorschlag, den niemand mehr braucht, verdeckt die // übrigen. const { admin, eigene } = await grundbestand(); await person(eigene.id, "Altlast", { aktiv: false }); await person(eigene.id, "Vertrieb"); expect((await ungepflegteAbteilungen(admin)).map((eintrag) => eintrag.name)).toEqual(["Vertrieb"]); }); it("schlägt nicht vor, was es archiviert schon gibt", async () => { // Der Name ist je Kunde eindeutig: `abteilungAnlegen` würde diesen Klick mit // „gibt es schon“ abweisen. Ein Knopf, der das tut, ist keiner. const { admin, eigene } = await grundbestand(); const abteilung = await abteilungAnlegen({ name: "Vertrieb" }, admin); await testPrisma.abteilung.update({ where: { id: abteilung.id }, data: { archiviert: true } }); await person(eigene.id, "Vertrieb"); expect(await ungepflegteAbteilungen(admin)).toEqual([]); await expect(abteilungAnlegen({ name: "Vertrieb" }, admin)).rejects.toThrow(/gibt es schon/); }); it("übernimmt einen Vorschlag – und zwar nur den Namen", async () => { const { admin, eigene } = await grundbestand(); await person(eigene.id, "Vertrieb"); const offen = await ungepflegteAbteilungen(admin); expect(offen).toHaveLength(1); const abteilung = await abteilungAnlegen({ name: offen[0]!.name, kundeId: offen[0]!.kundeId }, admin); expect(abteilung).toMatchObject({ name: "Vertrieb", zielOu: null, standardGruppen: [] }); expect(await ungepflegteAbteilungen(admin)).toEqual([]); }); describe("Mandantengrenze", () => { async function zweiKunden() { const { admin, eigene } = await grundbestand(Betriebsmodus.DIENSTLEISTUNG); const meiner = await testPrisma.kunde.create({ data: { name: "Meiner", kuerzel: "MEIN" } }); const fremder = await testPrisma.kunde.create({ data: { name: "Fremder", kuerzel: "FREMD" } }); const techniker = await testPrisma.benutzer.create({ data: { email: "t@firma.example", name: "Techniker", rolle: "TECHNIKER" }, }); await testPrisma.benutzerKunde.create({ data: { benutzerId: techniker.id, kundeId: meiner.id } }); process.env["OIDC_CUSTOMER_GROUP_PREFIX"] = "lz-kunde-"; return { admin, eigene, meiner, fremder, techniker: { id: techniker.id, rolle: techniker.rolle } }; } it("zeigt nur die Vorschläge der sichtbaren Kunden", async () => { const { meiner, fremder, techniker } = await zweiKunden(); await person(meiner.id, "Vertrieb"); await person(fremder.id, "Vertrieb"); await person(fremder.id, "Technik"); expect(await ungepflegteAbteilungen(techniker)).toEqual([ { name: "Vertrieb", anzahl: 1, kundeId: meiner.id }, ]); }); it("hält Kunden auseinander, die denselben Namen benutzen", async () => { // „Vertrieb“ ist bei einem Kunden gepflegt und beim anderen nicht. Ohne die // Gruppierung nach Kunde und Name verschwände der offene Fall — genau das // stand hier, bis der Review von #011 es gefunden hat. const { admin, meiner, fremder } = await zweiKunden(); await testPrisma.abteilung.create({ data: { kundeId: meiner.id, name: "Vertrieb" } }); await person(meiner.id, "Vertrieb"); await person(fremder.id, "Vertrieb"); expect(await ungepflegteAbteilungen(admin)).toEqual([ { name: "Vertrieb", anzahl: 1, kundeId: fremder.id }, ]); }); it("schlägt nichts für einen archivierten Kunden vor", async () => { // `kundeErmitteln` weist einen archivierten Kunden ab; der Klick auf den // Vorschlag ergäbe nur eine Fehlermeldung. const { admin, fremder } = await zweiKunden(); await person(fremder.id, "Vertrieb"); await testPrisma.kunde.update({ where: { id: fremder.id }, data: { archiviert: true } }); expect(await ungepflegteAbteilungen(admin)).toEqual([]); await expect(abteilungAnlegen({ name: "Vertrieb", kundeId: fremder.id }, admin)).rejects.toThrow( /archiviert/, ); }); }); });