diff --git a/prisma/seed.ts b/prisma/seed.ts index 5aabec8..9df837f 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,5 +1,7 @@ import { AbsenceReason, + AuditTargetType, + EventParticipationStatus, InvitationStatus, NotdienstAlertStatus, NotdienstPlanStatus, @@ -35,6 +37,9 @@ const DEMO_USER_EMAILS = [ "schmidt@waldameisen.local", "yilmaz@waldameisen.local", "pending@waldameisen.local", + "fischer@waldameisen.local", + "kowalski@waldameisen.local", + "weber@waldameisen.local", ]; const DEMO_VERIFICATION_TOKENS = [ @@ -293,11 +298,87 @@ async function createDemoUsers(passwordHash: string, consentAt: Date) { }, }); + const familyKowalski = await prisma.family.create({ + data: { + kitaId: kita.id, + name: "Familie Kowalski", + }, + }); + + const familyWeber = await prisma.family.create({ + data: { + kitaId: kita.id, + name: "Familie Weber", + }, + }); + + const elternFischer = await prisma.user.create({ + data: { + kitaId: kita.id, + familyId: familyFischer.id, + email: "fischer@waldameisen.local", + passwordHash, + firstName: "Frank", + lastName: "Fischer", + role: UserRole.ELTERN, + privacyPolicyAcceptedAt: consentAt, + privacyPolicyVersion: PRIVACY_POLICY_VERSION, + directoryOptInAt: consentAt, + emailVerifiedAt: consentAt, + phone: "+49 30 5555 1234", + street: "Fischerweg 4", + postalCode: "10247", + city: "Berlin", + }, + }); + + const elternKowalski = await prisma.user.create({ + data: { + kitaId: kita.id, + familyId: familyKowalski.id, + email: "kowalski@waldameisen.local", + passwordHash, + firstName: "Jan", + lastName: "Kowalski", + role: UserRole.ELTERN, + privacyPolicyAcceptedAt: consentAt, + privacyPolicyVersion: PRIVACY_POLICY_VERSION, + directoryOptInAt: consentAt, + emailVerifiedAt: consentAt, + phone: "+49 30 5555 5678", + street: "Grenzallee 12", + postalCode: "12057", + city: "Berlin", + }, + }); + + const elternWeber = await prisma.user.create({ + data: { + kitaId: kita.id, + familyId: familyWeber.id, + email: "weber@waldameisen.local", + passwordHash, + firstName: "Sabine", + lastName: "Weber", + role: UserRole.ELTERN, + privacyPolicyAcceptedAt: consentAt, + privacyPolicyVersion: PRIVACY_POLICY_VERSION, + directoryOptInAt: consentAt, + emailVerifiedAt: consentAt, + phone: "+49 30 5555 9012", + street: "Weberstrasse 7", + postalCode: "10249", + city: "Berlin", + }, + }); + return { kita, familyMueller, familySchmidtYilmaz, familyFischer, + familyKowalski, + familyWeber, superAdmin, admin, erzieherUser, @@ -305,6 +386,9 @@ async function createDemoUsers(passwordHash: string, consentAt: Date) { elternSchmidt, elternYilmaz, pendingParent, + elternFischer, + elternKowalski, + elternWeber, }; } @@ -313,6 +397,8 @@ async function createChildren({ familyMueller, familySchmidtYilmaz, familyFischer, + familyKowalski, + familyWeber, }: SeedContext) { const anna = await prisma.child.create({ data: { @@ -365,7 +451,27 @@ async function createChildren({ }, }); - return { anna, ben, clara, emil, nina }; + const leo = await prisma.child.create({ + data: { + kitaId: kita.id, + familyId: familyKowalski.id, + firstName: "Leo", + lastName: "Kowalski", + dateOfBirth: new Date("2022-08-12"), + }, + }); + + const mia = await prisma.child.create({ + data: { + kitaId: kita.id, + familyId: familyWeber.id, + firstName: "Mia", + lastName: "Weber", + dateOfBirth: new Date("2021-05-18"), + }, + }); + + return { anna, ben, clara, emil, nina, leo, mia }; } async function createEducators(kitaId: string) { @@ -530,11 +636,9 @@ async function createInvites({ kita, admin, pendingParent }: SeedContext) { }); } -async function createAnnouncements({ - kita, - admin, - koordinator, -}: SeedContext) { +async function createAnnouncements(context: SeedContext) { + const { kita, admin, koordinator, elternSchmidt, elternYilmaz, elternFischer } = context; + const sommerfest = await prisma.announcement.create({ data: { kitaId: kita.id, @@ -545,7 +649,7 @@ async function createAnnouncements({ }, }); - await prisma.announcement.create({ + const garderobe = await prisma.announcement.create({ data: { kitaId: kita.id, title: "Neue Garderoben-Regelung", @@ -555,21 +659,30 @@ async function createAnnouncements({ }, }); - await prisma.announcementRead.create({ + await prisma.attachment.create({ data: { - userId: koordinator.id, announcementId: sommerfest.id, + fileName: "sommerfest_ablauf.pdf", + fileUrl: "https://example.com/sommerfest_ablauf.pdf", + fileType: "application/pdf", }, }); + + await prisma.announcementRead.createMany({ + data: [ + { userId: koordinator.id, announcementId: sommerfest.id }, + { userId: elternSchmidt.id, announcementId: sommerfest.id }, + { userId: elternYilmaz.id, announcementId: sommerfest.id }, + { userId: elternFischer.id, announcementId: garderobe.id }, + ], + }); } -async function createTermine({ - kita, - admin, - koordinator, - elternSchmidt, - elternYilmaz, -}: SeedContext) { +async function createTermine( + context: SeedContext, + children: Awaited>, +) { + const { kita, admin, koordinator, elternSchmidt, elternYilmaz, elternFischer, elternKowalski } = context; const now = new Date(); const elternabend = await prisma.termin.create({ @@ -636,6 +749,65 @@ async function createTermine({ }, }); + const zooAusflug = await prisma.termin.create({ + data: { + kitaId: kita.id, + title: "Ausflug in den Zoo", + description: "Gemeinsamer Ausflug der gesamten Kita-Gruppe in den Berliner Zoo.", + type: TerminType.SONSTIGES, + status: TerminStatus.CONFIRMED, + startDate: addDays(now, 15), + endDate: addDays(now, 15), + allDay: true, + requiresRsvp: true, + rsvpDeadline: addDays(now, 5), + participantInfo: "Bitte wetterfeste Kleidung und Rucksack-Verpflegung mitbringen.", + createdById: admin.id, + approvedById: admin.id, + approvedAt: now, + }, + }); + + await prisma.eventParticipation.createMany({ + data: [ + { kitaId: kita.id, eventId: zooAusflug.id, childId: children.anna.id, status: EventParticipationStatus.ATTENDING }, + { kitaId: kita.id, eventId: zooAusflug.id, childId: children.clara.id, status: EventParticipationStatus.ATTENDING }, + { kitaId: kita.id, eventId: zooAusflug.id, childId: children.emil.id, status: EventParticipationStatus.NOT_ATTENDING }, + { kitaId: kita.id, eventId: zooAusflug.id, childId: children.leo.id, status: EventParticipationStatus.ATTENDING }, + ], + }); + + await prisma.termin.create({ + data: { + kitaId: kita.id, + title: "Mitmach-Tag (Garten)", + description: "Gemeinsames Herrichten des Gartens fuer die warme Jahreszeit. (Abgesagt wegen Dauerregen)", + type: TerminType.MITMACH_TAG, + status: TerminStatus.CANCELLED, + startDate: addDays(now, 2), + endDate: addDays(now, 2), + allDay: false, + createdById: admin.id, + }, + }); + + const sommerfestEvent = await prisma.termin.create({ + data: { + kitaId: kita.id, + title: "Sommerfest Waldameisen", + description: "Unser jaehrliches grosses Sommerfest im Kita-Garten mit Buffet und Spielstationen.", + type: TerminType.KITA_FEST, + status: TerminStatus.CONFIRMED, + startDate: addDays(now, 30), + endDate: addDays(now, 30), + allDay: false, + mitbringselListEnabled: true, + createdById: admin.id, + approvedById: admin.id, + approvedAt: now, + }, + }); + await prisma.mitbringselItem.createMany({ data: [ { @@ -650,15 +822,34 @@ async function createTermine({ userId: elternSchmidt.id, content: "Brot und Aufstrich", }, + { + kitaId: kita.id, + terminId: sommerfestEvent.id, + userId: elternYilmaz.id, + content: "Nudelsalat (vegan)", + }, + { + kitaId: kita.id, + terminId: sommerfestEvent.id, + userId: elternFischer.id, + content: "Mehrweg-Becher (ca. 30 Stk.)", + }, + { + kitaId: kita.id, + terminId: sommerfestEvent.id, + userId: elternKowalski.id, + content: "Apfelsaft & Wasser", + }, ], }); } async function createNotdienstData( - { kita, koordinator, elternSchmidt, elternYilmaz }: SeedContext, + context: SeedContext, children: Awaited>, educators: Awaited>, ) { + const { kita, koordinator, elternSchmidt, elternYilmaz, elternWeber, elternKowalski } = context; const today = dateOnly(new Date()); const currentMonth = startOfMonth(today); const previousMonth = getPreviousMonth(today); @@ -670,6 +861,8 @@ async function createNotdienstData( { childId: children.clara.id, userId: elternSchmidt.id }, { childId: children.emil.id, userId: elternYilmaz.id }, { childId: children.ben.id, userId: koordinator.id }, + { childId: children.leo.id, userId: elternKowalski.id }, + { childId: children.mia.id, userId: elternWeber.id }, ]; const targetWorkingDays = getWorkingDays( @@ -710,6 +903,30 @@ async function createNotdienstData( }, }); + const alertAssignmentDate = addDays(today, 3); + const pendingAlertAssignment = await prisma.notdienstAssignment.create({ + data: { + kitaId: kita.id, + planId: currentPlan.id, + childId: children.emil.id, + date: alertAssignmentDate, + }, + }); + + await prisma.notdienstAlert.create({ + data: { + kitaId: kita.id, + assignmentId: pendingAlertAssignment.id, + parentUserId: elternYilmaz.id, + triggeredById: koordinator.id, + educatorId: educators.petra.id, + status: NotdienstAlertStatus.PENDING, + confirmationToken: "demo-pending-alert-token", + triggeredAt: today, + notes: "Es fehlen zwei Kraefte. Bitte Notdienst besetzen.", + }, + }); + const previousPlan = await prisma.notdienstPlan.create({ data: { kitaId: kita.id, @@ -744,6 +961,60 @@ async function createNotdienstData( notes: "Beispiel-Alarm aus Seed-Daten.", }, }); + + const draftPlan = await prisma.notdienstPlan.create({ + data: { + kitaId: kita.id, + year: targetMonth.getFullYear(), + month: targetMonth.getMonth() + 1, + status: NotdienstPlanStatus.DRAFT, + createdById: koordinator.id, + }, + }); +} + +async function createAuditLogs({ kita, superAdmin, admin }: SeedContext) { + await prisma.auditLog.createMany({ + data: [ + { + actorUserId: superAdmin.id, + actorEmail: superAdmin.email, + action: "KITA_CREATE", + targetType: AuditTargetType.KITA, + targetId: kita.id, + targetLabel: kita.name, + targetKitaId: kita.id, + metadata: { name: kita.name, slug: kita.slug }, + createdAt: addDays(new Date(), -30), + }, + { + actorUserId: superAdmin.id, + actorEmail: superAdmin.email, + action: "USER_ROLE_UPDATE", + targetType: AuditTargetType.USER, + targetId: admin.id, + targetLabel: admin.email, + targetKitaId: kita.id, + metadata: { oldRole: "ELTERN", newRole: "ADMIN" }, + createdAt: addDays(new Date(), -28), + }, + { + actorUserId: admin.id, + actorEmail: admin.email, + action: "KITA_MODULE_UPDATE", + targetType: AuditTargetType.KITA, + targetId: kita.id, + targetLabel: kita.name, + targetKitaId: kita.id, + metadata: { + notdienstModuleEnabled: true, + terminModuleEnabled: true, + adressbuchModuleEnabled: true, + }, + createdAt: addDays(new Date(), -25), + }, + ], + }); } async function createDemoData() { @@ -760,8 +1031,9 @@ async function createDemoData() { await createAbsences(context, children); await createInvites(context); await createAnnouncements(context); - await createTermine(context); + await createTermine(context, children); await createNotdienstData(context, children, educators); + await createAuditLogs(context); printSummary(context, children); } @@ -776,7 +1048,10 @@ async function seedIfEmpty() { } function printSummary( - { + context: SeedContext, + children: Awaited>, +) { + const { kita, superAdmin, admin, @@ -784,10 +1059,11 @@ function printSummary( koordinator, elternSchmidt, elternYilmaz, + elternFischer, + elternKowalski, + elternWeber, pendingParent, - }: SeedContext, - children: Awaited>, -) { + } = context; console.log("Seed complete"); console.log(""); console.log(` Kita: ${kita.name} (${kita.slug})`); @@ -799,6 +1075,9 @@ function printSummary( console.log(` Koordinator: ${koordinator.email}`); console.log(` Eltern: ${elternSchmidt.email}`); console.log(` Eltern: ${elternYilmaz.email}`); + console.log(` Eltern (Fischer): ${elternFischer.email}`); + console.log(` Eltern (Kowalski): ${elternKowalski.email}`); + console.log(` Eltern (Weber): ${elternWeber.email}`); console.log(""); console.log( ` Offener Invite: ${pendingParent.email} -> /invite/demo-pending-parent-token`,