158 lines
5.7 KiB
TypeScript
158 lines
5.7 KiB
TypeScript
#!/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();
|