Add non-destructive dev seed on startup
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
"use server";
|
||||
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { UserRole } from "@prisma/client";
|
||||
import { z } from "zod";
|
||||
|
||||
import { requireRole } from "@/lib/auth-utils";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { getTargetMonthData } from "@/lib/date-utils";
|
||||
|
||||
// =====================================================================
|
||||
// /dashboard/notdienst · Server Actions
|
||||
// ---------------------------------------------------------------------
|
||||
// Speichert die gebuchten Termine der Eltern im Zielmonat.
|
||||
// Die Termine werden Round-Robin auf die Kinder aufgeteilt.
|
||||
// =====================================================================
|
||||
|
||||
const payloadSchema = z.object({
|
||||
childrenIds: z.array(z.string()).min(1),
|
||||
dates: z.array(z.string().datetime()), // ISO strings
|
||||
});
|
||||
|
||||
export async function saveNotdienstAvailabilities(payloadRaw: {
|
||||
childrenIds: string[];
|
||||
dates: string[];
|
||||
}) {
|
||||
const session = await requireRole([
|
||||
UserRole.ELTERN,
|
||||
UserRole.ADMIN,
|
||||
UserRole.KOORDINATOR,
|
||||
]);
|
||||
|
||||
const parsed = payloadSchema.safeParse(payloadRaw);
|
||||
if (!parsed.success) {
|
||||
return { error: "Ungültige Eingabedaten." };
|
||||
}
|
||||
|
||||
const { childrenIds, dates } = parsed.data;
|
||||
|
||||
// ── 1. Sperrfrist prüfen ───────────────────────────────────────────
|
||||
const { targetYear, targetMonth, isLocked } = getTargetMonthData();
|
||||
if (isLocked) {
|
||||
return { error: "Die Planung für diesen Monat ist bereits abgeschlossen." };
|
||||
}
|
||||
|
||||
const kitaId = session.user.kitaId;
|
||||
if (!kitaId) {
|
||||
return { error: "Kein Mandant zugeordnet." };
|
||||
}
|
||||
|
||||
// ── 2. Validierung (Soll-Tage) ─────────────────────────────────────
|
||||
const kita = await prisma.kita.findUniqueOrThrow({
|
||||
where: { id: kitaId },
|
||||
select: { notdienstMinPerChildPerMonth: true },
|
||||
});
|
||||
|
||||
const requiredTotal = childrenIds.length * kita.notdienstMinPerChildPerMonth;
|
||||
if (dates.length < requiredTotal) {
|
||||
return {
|
||||
error: `Bitte wähle mindestens ${requiredTotal} Tage aus.`,
|
||||
};
|
||||
}
|
||||
|
||||
// Sicherstellen, dass alle Kinder zum angemeldeten User gehören und zur kitaId passen
|
||||
const validChildren = await prisma.child.findMany({
|
||||
where: {
|
||||
id: { in: childrenIds },
|
||||
kitaId,
|
||||
parentLinks: { some: { userId: session.user.id } },
|
||||
},
|
||||
select: { id: true },
|
||||
});
|
||||
|
||||
if (validChildren.length !== childrenIds.length) {
|
||||
return { error: "Ungültige Kinder-Zuordnung erkannt." };
|
||||
}
|
||||
|
||||
// Termine in Date-Objekte wandeln und sortieren
|
||||
const parsedDates = dates
|
||||
.map((d) => new Date(d))
|
||||
.sort((a, b) => a.getTime() - b.getTime());
|
||||
|
||||
// Round-Robin Zuweisung
|
||||
const inserts: {
|
||||
kitaId: string;
|
||||
childId: string;
|
||||
userId: string;
|
||||
date: Date;
|
||||
}[] = [];
|
||||
|
||||
for (let i = 0; i < parsedDates.length; i++) {
|
||||
const childId = validChildren[i % validChildren.length].id;
|
||||
inserts.push({
|
||||
kitaId,
|
||||
childId,
|
||||
userId: session.user.id,
|
||||
date: parsedDates[i],
|
||||
});
|
||||
}
|
||||
|
||||
// ── 3. Datenbank-Transaktion ───────────────────────────────────────
|
||||
try {
|
||||
await prisma.$transaction(async (tx) => {
|
||||
// a) Alle *eigenen* bestehenden Einträge im Zielmonat für diese Kinder löschen
|
||||
await tx.notdienstAvailability.deleteMany({
|
||||
where: {
|
||||
kitaId,
|
||||
userId: session.user.id,
|
||||
childId: { in: childrenIds },
|
||||
date: {
|
||||
gte: new Date(targetYear, targetMonth - 1, 1),
|
||||
lt: new Date(targetYear, targetMonth, 1),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// b) Neue Einträge setzen
|
||||
if (inserts.length > 0) {
|
||||
await tx.notdienstAvailability.createMany({
|
||||
data: inserts,
|
||||
skipDuplicates: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
revalidatePath("/dashboard/notdienst");
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Speichern der Notdienste:", error);
|
||||
return { error: "Ein Fehler ist aufgetreten beim Speichern der Termine." };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user