#!/usr/bin/env tsx /** * Beispiel-Stammdaten fuer die Screenshots (#011). * * Personen, Abteilungen und Geraete lassen sich nur mit Inhalt zeigen, und die * echten Beispieldaten kommen erst mit #017. Bis dahin legt dieses Skript einen * kleinen, glaubwuerdigen Bestand an — darunter eine Person mit * `herkunft = ABGLEICH`, damit die gesperrten Stammdaten sichtbar werden. * * Es geht durch die echten Dienste, wo es welche gibt: waeren die Regeln anders * als hier angenommen, schlaegt es fehl, statt eine Lage herzustellen, die es in * der Anwendung nie gibt. Der abgeglichene Fall entsteht direkt ueber Prisma — * den Weg dorthin baut erst der Verzeichnisabgleich (#016). * * Idempotent. Mit #017 wird das Skript geloescht. * * pnpm beispiel:stammdaten */ import "dotenv/config"; import { Herkunft } from "../src/generated/prisma/enums.js"; import { prisma } from "../src/lib/db.js"; import { abteilungAnlegen } from "../src/server/services/abteilungen.js"; import { geraetAnlegen } from "../src/server/services/geraete.js"; import { mitarbeiterAnlegen } from "../src/server/services/mitarbeiter.js"; const admin = await prisma.benutzer.findFirst({ where: { rolle: "ADMIN" }, orderBy: { erstelltAm: "asc" }, select: { id: true, rolle: true }, }); if (!admin) { throw new Error("Es gibt keinen Administrator. Erst pnpm db:seed laufen lassen."); } const handelnder = { id: admin.id, rolle: admin.rolle }; const eigene = await prisma.kunde.findFirstOrThrow({ where: { istEigeneOrganisation: true } }); const ABTEILUNGEN = [ { name: "Buchhaltung", zielOu: "OU=Buchhaltung,OU=Benutzer,DC=firma,DC=de", standardGruppen: ["G-Buchhaltung", "G-Alle"], mailDomain: "firma.de", }, { name: "Vertrieb", zielOu: "OU=Vertrieb,OU=Benutzer,DC=firma,DC=de", standardGruppen: ["G-Vertrieb", "G-Alle"], mailDomain: "firma.de", }, { name: "IT", zielOu: "OU=IT,OU=Benutzer,DC=firma,DC=de", standardGruppen: ["G-IT", "G-Alle", "G-Adminrechte"], mailDomain: "firma.de", }, ]; const PERSONEN = [ { vorname: "Maria", nachname: "Huber", sam: "mhuber", abteilung: "Buchhaltung", titel: "Sachbearbeiterin" }, { vorname: "Jörg", nachname: "Müller-Lüdenscheid", sam: "jmuellerluedensch", abteilung: "Vertrieb" }, { vorname: "Ali", nachname: "Demir", sam: "ademir", abteilung: "IT", titel: "Systemadministrator" }, { vorname: "Sonja", nachname: "Brand", sam: "sbrand", abteilung: "Vertrieb" }, ]; let neueAbteilungen = 0; for (const eingabe of ABTEILUNGEN) { const vorhanden = await prisma.abteilung.findUnique({ where: { kundeId_name: { kundeId: eigene.id, name: eingabe.name } }, }); if (vorhanden) continue; await abteilungAnlegen(eingabe, handelnder); neueAbteilungen += 1; } let neuePersonen = 0; for (const person of PERSONEN) { const vorhanden = await prisma.mitarbeiter.findFirst({ where: { sam: person.sam } }); if (vorhanden) continue; const mail = `${person.sam}@firma.de`; await mitarbeiterAnlegen({ ...person, mail, upn: mail }, handelnder); neuePersonen += 1; } /** * Eine Person aus dem Verzeichnis. * * Direkt ueber Prisma, weil der Dienst nur `herkunft = MANUELL` anlegt — den * anderen Weg baut der Verzeichnisabgleich (#016). Fuer den Screenshot der * gesperrten Stammdaten braucht es sie trotzdem schon jetzt. */ const abgeglichen = await prisma.mitarbeiter.findFirst({ where: { sam: "kwinter" } }); if (!abgeglichen) { await prisma.mitarbeiter.create({ data: { kundeId: eigene.id, vorname: "Katrin", nachname: "Winter", anzeigename: "Katrin Winter", mail: "kwinter@firma.de", upn: "kwinter@firma.de", sam: "kwinter", abteilung: "Einkauf", titel: "Einkäuferin", dn: "CN=Katrin Winter,OU=Einkauf,OU=Benutzer,DC=firma,DC=de", herkunft: Herkunft.ABGLEICH, zuletztGesehenAm: new Date(), }, }); neuePersonen += 1; } /** * Ein paar Geraete, darunter eines ohne Hostname. * * `PC-001` und `NB-001` heissen so, weil der Auftrag sie in den Beispieldaten * nennt; der Serverschrank zeigt den Fall „Bezeichnung statt Hostname“, den die * Pflichtregel ausdruecklich erlaubt. */ const GERAETE = [ { hostname: "PC-001", typ: "PC" as const, modell: "Dell OptiPlex 7010", besitzer: "mhuber" }, { hostname: "NB-001", typ: "NOTEBOOK" as const, modell: "Lenovo T14", besitzer: "jmuellerluedensch" }, { hostname: "SRV-DC01", typ: "SERVER" as const, modell: "Dell PowerEdge R450" }, { bezeichnung: "Serverschrank Keller", typ: "SONSTIGES" as const }, { hostname: "PRN-EG-01", typ: "DRUCKER" as const, modell: "Kyocera ECOSYS" }, ]; let neueGeraete = 0; for (const geraet of GERAETE) { // Seriennummern haben keine Leerzeichen – auch die erfundenen nicht. const kennzeichen = (geraet.hostname ?? geraet.bezeichnung ?? "").replace(/\s+/gu, "-").toUpperCase(); const vorhanden = await prisma.geraet.findFirst({ where: geraet.hostname ? { hostname: geraet.hostname } : { bezeichnung: geraet.bezeichnung }, }); if (vorhanden) continue; const besitzer = geraet.besitzer ? await prisma.mitarbeiter.findFirst({ where: { sam: geraet.besitzer }, select: { id: true } }) : null; await geraetAnlegen( { ...(geraet.hostname ? { hostname: geraet.hostname } : {}), ...(geraet.bezeichnung ? { bezeichnung: geraet.bezeichnung } : {}), ...(geraet.modell ? { modell: geraet.modell } : {}), ...(besitzer ? { mitarbeiterId: besitzer.id } : {}), typ: geraet.typ, seriennummer: `SN-${kennzeichen}`, }, handelnder, ); neueGeraete += 1; } console.log( `Beispiel-Stammdaten: ${neueAbteilungen} Abteilungen, ${neuePersonen} Personen und ` + `${neueGeraete} Geräte neu angelegt.`, ); await prisma.$disconnect();