142 lines
5.3 KiB
TypeScript
142 lines
5.3 KiB
TypeScript
#!/usr/bin/env tsx
|
||
/**
|
||
* Beispiel-Laeufe fuer die Screenshots (#013).
|
||
*
|
||
* Eine Abarbeitungsansicht ohne Lauf zeigt nichts, und die echten Beispieldaten
|
||
* kommen erst mit #017. Bis dahin legt dieses Skript zwei Laeufe an: einen
|
||
* begonnenen mit Fortschritt, Notiz und Kommentar, und einen vorbereiteten im
|
||
* Zustand `OFFEN` — der Fall, den der Auftrag ausdruecklich verlangt (ein
|
||
* Kollege richtet ein, der Techniker scannt und arbeitet ab).
|
||
*
|
||
* Es geht durch die echten Dienste. Waeren die Regeln anders als hier
|
||
* angenommen, schlaegt es fehl, statt eine Lage herzustellen, die es in der
|
||
* Anwendung nie gibt.
|
||
*
|
||
* Idempotent.
|
||
*
|
||
* **Bleibt auch nach #017.** Der Kopf sagte frueher „Mit #017 wird das Skript
|
||
* geloescht“ — das war eine Verwechslung zweier Dinge. Der Seed richtet eine
|
||
* **Installation** ein: Vorlagen, Abteilungen, Personen, Geraete. Was
|
||
* Screenshots und Ende-zu-Ende-Abläufe brauchen, ist etwas anderes: ein offener
|
||
* Entwurf, ein halb abgearbeiteter Lauf, eine Person aus dem Verzeichnis. Das in
|
||
* den Seed zu legen hiesse, jeder frischen Installation Demo-Laeufe mitzugeben,
|
||
* die dort niemand bestellt hat. Die Zusammenfuehrung dieser Fixtures gehoert zu
|
||
* #018.
|
||
*
|
||
* pnpm beispiel:lauf
|
||
*/
|
||
import "dotenv/config";
|
||
import { SchrittZustand } from "../src/generated/prisma/enums.js";
|
||
import { prisma } from "../src/lib/db.js";
|
||
import { kommentarHinzufuegen } from "../src/server/services/kommentare.js";
|
||
import { laufAnlegen, laufZurBearbeitungOeffnen } from "../src/server/services/laeufe.js";
|
||
import { schrittergebnisSetzen } from "../src/server/services/schrittergebnisse.js";
|
||
|
||
const VORLAGE = "PC-Neuinstallation (Beispiel)";
|
||
|
||
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 version = await prisma.vorlagenVersion.findFirst({
|
||
where: { status: "VEROEFFENTLICHT", vorlage: { name: VORLAGE } },
|
||
orderBy: { version: "desc" },
|
||
select: { id: true },
|
||
});
|
||
if (!version) {
|
||
throw new Error(`Es gibt keine veröffentlichte Version von „${VORLAGE}“. Erst pnpm beispiel:vorlage.`);
|
||
}
|
||
|
||
const geraet = await prisma.geraet.findFirst({ where: { hostname: "NB-001" }, select: { id: true } });
|
||
const person = await prisma.mitarbeiter.findFirst({ where: { sam: "mhuber" }, select: { id: true } });
|
||
if (!geraet || !person) {
|
||
throw new Error("NB-001 oder mhuber fehlen. Erst pnpm beispiel:stammdaten laufen lassen.");
|
||
}
|
||
const abteilung = await prisma.abteilung.findFirst({
|
||
where: { name: "Buchhaltung" },
|
||
select: { id: true },
|
||
});
|
||
|
||
/** Die Schritte des ersten Abschnitts, in ihrer Reihenfolge. */
|
||
const abschnitt = await prisma.vorlagenAbschnitt.findFirstOrThrow({
|
||
where: { versionId: version.id },
|
||
orderBy: { position: "asc" },
|
||
select: { schritte: { orderBy: { position: "asc" }, select: { id: true, titel: true } } },
|
||
});
|
||
|
||
const TITEL_BEGONNEN = "PC-Neuinstallation · NB-001 · Maria Huber";
|
||
const TITEL_OFFEN = "PC-Neuinstallation · PC-001 · vorbereitet";
|
||
|
||
const schonDa = await prisma.lauf.findFirst({ where: { titel: TITEL_BEGONNEN }, select: { id: true } });
|
||
if (schonDa) {
|
||
console.log("Die Beispiel-Läufe gibt es schon – nichts zu tun.");
|
||
} else {
|
||
const begonnen = await laufAnlegen(
|
||
{
|
||
vorlagenVersionId: version.id,
|
||
titel: TITEL_BEGONNEN,
|
||
geraetId: geraet.id,
|
||
mitarbeiterId: person.id,
|
||
abteilungId: abteilung?.id ?? null,
|
||
ticket: "TIK-4711",
|
||
variablen: { os_version: "Windows 11 Pro 24H2", join_typ: "Active Directory", arbeitsspeicher: 16 },
|
||
zugewiesenAnId: admin.id,
|
||
},
|
||
handelnder,
|
||
);
|
||
await laufZurBearbeitungOeffnen(begonnen.id, handelnder);
|
||
|
||
// Zwei erledigte Schritte und einer, der nicht zutrifft: so zeigt der
|
||
// Fortschrittsbalken einen echten Stand und die Begruendung steht am Schritt.
|
||
const [erster, zweiter, dritter] = abschnitt.schritte;
|
||
for (const schritt of [erster, zweiter]) {
|
||
if (!schritt) continue;
|
||
await schrittergebnisSetzen(
|
||
{ laufId: begonnen.id, vorlagenSchrittId: schritt.id, zustand: SchrittZustand.ERLEDIGT },
|
||
handelnder,
|
||
);
|
||
}
|
||
if (dritter) {
|
||
await schrittergebnisSetzen(
|
||
{
|
||
laufId: begonnen.id,
|
||
vorlagenSchrittId: dritter.id,
|
||
zustand: SchrittZustand.NICHT_ZUTREFFEND,
|
||
notiz: "Gerät ist neu ausgepackt – es gibt noch keine Altdaten.",
|
||
},
|
||
handelnder,
|
||
);
|
||
}
|
||
await kommentarHinzufuegen(
|
||
{
|
||
laufId: begonnen.id,
|
||
rumpf: "Rückfrage an die Buchhaltung: Steuer-Software wird erst nächste Woche gebraucht.",
|
||
},
|
||
handelnder,
|
||
);
|
||
|
||
const pc001 = await prisma.geraet.findFirst({ where: { hostname: "PC-001" }, select: { id: true } });
|
||
const morgen = new Date(Date.now() + 24 * 60 * 60 * 1000);
|
||
await laufAnlegen(
|
||
{
|
||
vorlagenVersionId: version.id,
|
||
titel: TITEL_OFFEN,
|
||
geraetId: pc001?.id ?? null,
|
||
variablen: { os_version: "Windows 11 Pro 24H2", join_typ: "Active Directory" },
|
||
ticket: "TIK-4712",
|
||
zugewiesenAnId: admin.id,
|
||
faelligAm: morgen,
|
||
},
|
||
handelnder,
|
||
);
|
||
console.log("Zwei Beispiel-Läufe angelegt: einer in Arbeit, einer vorbereitet.");
|
||
}
|
||
|
||
await prisma.$disconnect();
|