test: Demodaten und Unit- sowie PostgreSQL-Tests ergänzen
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
1 parent
c1513c040b
commit
ef52cc1218
3 files changed
+519
No files matched your search
@@ -0,0 +1,107 @@
|
||||
import "dotenv/config";
|
||||
import { db } from "../src/lib/db";
|
||||
import { auditContext } from "../src/lib/audit";
|
||||
import { localClock, localInstant } from "../src/lib/time";
|
||||
import { getSlots } from "../src/lib/slots";
|
||||
|
||||
const demoChildren = [
|
||||
["Mila", "Sonnental", "1a"], ["Noah", "Wiesenbach", "2b"], ["Emma", "Blütenfeld", "3a"],
|
||||
["Finn", "Wolkenstein", "1b"], ["Lina", "Sommerhain", "2a"], ["Ben", "Sternwald", "4a"],
|
||||
["Hannah", "Lindenau", "3b"], ["Leon", "Regenbogen", "1a"], ["Clara", "Morgenrot", "2b"],
|
||||
["Elias", "Birkenfels", "4b"], ["Amelie", "Fuchswiese", "3a"], ["Oskar", "Kleebach", "2a"],
|
||||
];
|
||||
const clockTime = (minutes: number) => {
|
||||
const clamped = Math.max(1, Math.min(1439, minutes));
|
||||
return `${Math.floor(clamped / 60).toString().padStart(2, "0")}:${(clamped % 60).toString().padStart(2, "0")}`;
|
||||
};
|
||||
|
||||
async function seed() {
|
||||
const staff = await db.query<{ id: string }>("SELECT id FROM staff ORDER BY created_at, id LIMIT 1");
|
||||
if (!staff.rowCount) throw new Error("Zuerst npm run db:setup ausführen.");
|
||||
const client = await db.connect();
|
||||
const now = new Date();
|
||||
const clock = localClock(now);
|
||||
const timeZone = process.env.APP_TIMEZONE ?? "Europe/Berlin";
|
||||
const slots = (await getSlots()).filter((slot) => slot.active);
|
||||
const currentMinute = Number(clock.time.slice(0, 2)) * 60 + Number(clock.time.slice(3, 5));
|
||||
let inserted = 0;
|
||||
try {
|
||||
await client.query("BEGIN");
|
||||
await auditContext(client, staff.rows[0].id, "Fiktive Demodaten zum Testen – keine realen Personen.");
|
||||
for (const [index, [firstName, lastName, className]] of demoChildren.entries()) {
|
||||
const id = `d3000000-0000-4000-8000-${(index + 1).toString().padStart(12, "0")}`;
|
||||
const result = await client.query(`INSERT INTO children(id, first_name, last_name, class_name)
|
||||
VALUES ($1, $2, $3, $4) ON CONFLICT(id) DO NOTHING RETURNING id`, [id, firstName, lastName, className]);
|
||||
if (!result.rowCount) continue;
|
||||
inserted++;
|
||||
const weekdays = [...new Set([1, 2, 3, 4, 5, clock.weekday])];
|
||||
for (const weekday of weekdays) {
|
||||
const slot = slots.length ? slots[(index + weekday) % slots.length] : undefined;
|
||||
await client.query(`INSERT INTO weekly_schedules(child_id, weekday, arrival, pickup, pickup_end, pickup_slot_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)`,
|
||||
[id, weekday, weekday % 2 ? "12:00" : "12:30", slot?.start ?? "16:00", slot?.end ?? null, slot?.id ?? null]);
|
||||
}
|
||||
await client.query(`INSERT INTO pickup_contacts(child_id, name, relationship, authorized, notes) VALUES
|
||||
($1, $2, 'Mutter', true, 'Fiktiver Demokontakt. Ausweis bei unbekannter Person prüfen.'),
|
||||
($1, $3, 'Vater', true, 'Fiktiver Demokontakt.')`,
|
||||
[id, `Alex ${lastName}`, `Robin ${lastName}`]);
|
||||
if (index % 3 === 0) {
|
||||
await client.query(`INSERT INTO pickup_contacts(child_id, name, relationship, authorized, notes)
|
||||
VALUES ($1, $2, 'Bekannte Person', false, 'Demobeispiel: keine aktuelle Abholberechtigung.')`, [id, `Kim ${lastName}`]);
|
||||
}
|
||||
if ([2, 5, 9].includes(index)) {
|
||||
for (const weekday of weekdays) {
|
||||
await client.query("INSERT INTO alone_rules(child_id, weekday, earliest) VALUES ($1, $2, $3)",
|
||||
[id, weekday, weekday === clock.weekday ? clockTime(currentMinute - 10) : "15:00"]);
|
||||
}
|
||||
}
|
||||
let historyIndex = 0;
|
||||
for (let offset = 1; offset <= 14; offset++) {
|
||||
const date = new Date(`${clock.day}T12:00:00Z`);
|
||||
date.setUTCDate(date.getUTCDate() - offset);
|
||||
if ([0, 6].includes(date.getUTCDay())) continue;
|
||||
const day = date.toISOString().slice(0, 10);
|
||||
const sick = (index + offset) % 11 === 0;
|
||||
const forgotten = index === 0 && historyIndex === 0;
|
||||
historyIndex++;
|
||||
const arrival = sick ? null : localInstant(day, "12:15", timeZone);
|
||||
const pickup = sick || forgotten ? null : localInstant(day, clockTime(14 * 60 + (index % 5) * 30), timeZone);
|
||||
await client.query(`INSERT INTO attendance(child_id, day, status, arrived_at, picked_up_at, pickup_kind, updated_by)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)`, [id, day,
|
||||
sick ? "sick" : forgotten ? "arrived" : "picked_up", arrival, pickup,
|
||||
pickup ? index % 4 === 0 ? "parents" : "planned" : null, staff.rows[0].id]);
|
||||
}
|
||||
const plannedPickup = clockTime(currentMinute + (index === 0 ? -10 : index === 1 || index === 2 ? 10 : 120 + index * 10));
|
||||
const arrivalTime = clockTime(currentMinute - 90);
|
||||
if (index === 8) {
|
||||
await client.query("INSERT INTO day_overrides(child_id, day, attending) VALUES ($1, $2, false)", [id, clock.day]);
|
||||
} else {
|
||||
await client.query(`INSERT INTO day_overrides(child_id, day, attending, arrival, pickup)
|
||||
VALUES ($1, $2, true, $3, $4)`, [id, clock.day, "00:00", plannedPickup]);
|
||||
}
|
||||
if ([7, 8, 10].includes(index) || currentMinute < 3) continue;
|
||||
const sick = index === 4;
|
||||
const picked = index === 5 || index === 6;
|
||||
await client.query(`INSERT INTO attendance(child_id, day, status, arrived_at, picked_up_at, pickup_kind, updated_by)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)`, [id, clock.day, sick ? "sick" : picked ? "picked_up" : "arrived",
|
||||
sick ? null : localInstant(clock.day, arrivalTime, timeZone),
|
||||
picked ? localInstant(clock.day, clockTime(currentMinute - 5), timeZone) : null,
|
||||
picked ? index === 5 ? "parents" : "planned" : null, staff.rows[0].id]);
|
||||
}
|
||||
await client.query("COMMIT");
|
||||
console.log(`${inserted} fiktive Kinder angelegt (${demoChildren.length - inserted} bereits vorhanden, unverändert).`);
|
||||
console.log("Mit Wochenplänen, Tagesabweichungen, Abholberechtigten und zwei Wochen Verlauf.");
|
||||
console.log("Mila Sonnental hat im letzten Betreuungstag eine vergessene Abholung zum Korrigieren.");
|
||||
console.log("Passwörter und bestehende Datensätze wurden nicht verändert.");
|
||||
} catch (error) {
|
||||
await client.query("ROLLBACK");
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
seed().catch((error: unknown) => {
|
||||
console.error("Demodaten konnten nicht angelegt werden:", error);
|
||||
process.exitCode = 1;
|
||||
}).finally(() => db.end());
|
||||
Reference in new issue
Block a user