feat: complete notdienst planning, quick wins and notifications

This commit is contained in:
t.indorf
2026-10-12 15:34:09 +02:00
parent b915857951
commit 00f602a7aa
50 changed files with 2443 additions and 513 deletions
@@ -0,0 +1,47 @@
BEGIN;
CREATE TABLE "notdienst_emails" (
"id" TEXT NOT NULL,
"kitaId" TEXT NOT NULL,
"familyId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"planId" TEXT,
"year" INTEGER NOT NULL,
"month" INTEGER NOT NULL,
"kind" TEXT NOT NULL,
"eventKey" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"sentAt" TIMESTAMP(3),
"skippedAt" TIMESTAMP(3),
"leaseUntil" TIMESTAMP(3),
"claimToken" TEXT,
"nextAttemptAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"failed" BOOLEAN NOT NULL DEFAULT false,
"attempts" INTEGER NOT NULL DEFAULT 0,
"lastError" TEXT,
CONSTRAINT "notdienst_emails_pkey" PRIMARY KEY ("id"),
CONSTRAINT "notdienst_emails_month_check" CHECK ("month" BETWEEN 1 AND 12),
CONSTRAINT "notdienst_emails_kind_check" CHECK ("kind" IN ('REMINDER','PUBLICATION')),
CONSTRAINT "notdienst_emails_plan_check" CHECK (("kind" = 'PUBLICATION' AND "planId" IS NOT NULL) OR ("kind" = 'REMINDER' AND "planId" IS NULL))
);
CREATE UNIQUE INDEX "notdienst_emails_kitaId_userId_kind_year_month_eventKey_key" ON "notdienst_emails"("kitaId","userId","kind","year","month","eventKey");
CREATE INDEX "notdienst_emails_sentAt_skippedAt_nextAttemptAt_idx" ON "notdienst_emails"("sentAt","skippedAt","nextAttemptAt");
CREATE INDEX "notdienst_emails_kitaId_year_month_idx" ON "notdienst_emails"("kitaId","year","month");
ALTER TABLE "notdienst_emails" ADD CONSTRAINT "notdienst_emails_kitaId_fkey" FOREIGN KEY ("kitaId") REFERENCES "kitas"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "notdienst_emails" ADD CONSTRAINT "notdienst_emails_familyId_fkey" FOREIGN KEY ("familyId") REFERENCES "families"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "notdienst_emails" ADD CONSTRAINT "notdienst_emails_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "notdienst_emails" ADD CONSTRAINT "notdienst_emails_planId_fkey" FOREIGN KEY ("planId") REFERENCES "notdienst_plans"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "notdienst_emails" ADD CONSTRAINT "notdienst_emails_familyId_tenant_fkey" FOREIGN KEY ("familyId","kitaId") REFERENCES "families"("id","kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_emails" ADD CONSTRAINT "notdienst_emails_userId_tenant_fkey" FOREIGN KEY ("userId","kitaId") REFERENCES "users"("id","kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
ALTER TABLE "notdienst_emails" ADD CONSTRAINT "notdienst_emails_planId_tenant_fkey" FOREIGN KEY ("planId","kitaId") REFERENCES "notdienst_plans"("id","kitaId") ON DELETE NO ACTION ON UPDATE NO ACTION;
CREATE TABLE "notdienst_reminder_runs" (
"id" TEXT NOT NULL,
"kitaId" TEXT NOT NULL,
"year" INTEGER NOT NULL,
"month" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "notdienst_reminder_runs_pkey" PRIMARY KEY ("id"),
CONSTRAINT "notdienst_reminder_runs_month_check" CHECK ("month" BETWEEN 1 AND 12)
);
CREATE UNIQUE INDEX "notdienst_reminder_runs_kitaId_year_month_key" ON "notdienst_reminder_runs"("kitaId","year","month");
ALTER TABLE "notdienst_reminder_runs" ADD CONSTRAINT "notdienst_reminder_runs_kitaId_fkey" FOREIGN KEY ("kitaId") REFERENCES "kitas"("id") ON DELETE CASCADE ON UPDATE CASCADE;
COMMIT;
+49 -1
View File
@@ -159,7 +159,9 @@ model Kita {
termine Termin[]
mitbringselItems MitbringselItem[]
eventParticipations EventParticipation[]
notdienstPlans NotdienstPlan[]
notdienstEmails NotdienstEmail[]
notdienstReminderRuns NotdienstReminderRun[]
notdienstPlans NotdienstPlan[]
notdienstAvailabilities NotdienstAvailability[]
notdienstAssignments NotdienstAssignment[]
notdienstAlerts NotdienstAlert[]
@@ -184,6 +186,7 @@ model Family {
name String
notdienstAlarms NotdienstAlarm[]
notdienstEmails NotdienstEmail[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -275,6 +278,7 @@ model User {
alarmRecipients NotdienstAlarmRecipient[]
alarmNotifications NotdienstAlarmNotification[]
alarmEmails NotdienstAlarmEmail[]
notdienstEmails NotdienstEmail[]
@@index([kitaId])
@@index([familyId])
@@ -902,6 +906,7 @@ model NotdienstPlan {
updatedAt DateTime @updatedAt
assignments NotdienstAssignment[]
emails NotdienstEmail[]
@@unique([kitaId, year, month])
@@index([kitaId])
@@ -1208,3 +1213,46 @@ model PendingRegistration {
@@index([expiresAt])
@@map("pending_registrations")
}
/// Durable notification jobs. No bearer tokens or personal response links.
model NotdienstEmail {
id String @id @default(cuid())
kitaId String
kita Kita @relation(fields: [kitaId], references: [id], onDelete: Cascade)
familyId String
family Family @relation(fields: [familyId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
planId String?
plan NotdienstPlan? @relation(fields: [planId], references: [id], onDelete: Cascade)
year Int
month Int
kind String
eventKey String
createdAt DateTime @default(now())
sentAt DateTime?
skippedAt DateTime?
leaseUntil DateTime?
claimToken String?
nextAttemptAt DateTime @default(now())
failed Boolean @default(false)
attempts Int @default(0)
lastError String?
@@unique([kitaId, userId, kind, year, month, eventKey])
@@index([sentAt, skippedAt, nextAttemptAt])
@@index([kitaId, year, month])
@@map("notdienst_emails")
}
model NotdienstReminderRun {
id String @id @default(cuid())
kitaId String
kita Kita @relation(fields: [kitaId], references: [id], onDelete: Cascade)
year Int
month Int
createdAt DateTime @default(now())
@@unique([kitaId, year, month])
@@map("notdienst_reminder_runs")
}
+2
View File
@@ -1,3 +1,5 @@
-- HISTORISCHER UPGRADEPFAD: aktuelle Releases verwenden prisma/migrations und deploy/README.md.
-- Nicht zusätzlich zu versionierten Migrationen oder auf bereits aktualisierten Datenbanken ausführen.
-- CreateEnum
CREATE TYPE "RsvpMode" AS ENUM ('CHILD', 'FAMILY');