feat(260929-if2): Erinnerung zusaetzlich per E-Mail, Doku und Aenderungsliste
- E-Mail-Planer: Anspruch vor dem Senden (genau eine Mail je Faelligkeit, hoechstens 3 Versuche), Systemlesen nur fuer die Kandidatenabfrage - MailService.sendReminderEmail (Berliner Zeit, nur Text), GET /reminders/email-status, Haken im Formular mit Erklaerung - Zugriffsklassifikation und Erlaubnisliste fuer forSystem nachgezogen, Aenderungsliste und Anwenderanleitung Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { SettingsService } from '../settings/settings.service';
|
||||
import { forTenant } from '../prisma/prisma-tenant.extension';
|
||||
import type { CreateReminderDto, SnoozeReminderDto, UpdateReminderDto } from './dto/reminder.dto';
|
||||
|
||||
@@ -40,7 +41,35 @@ const MAX_AHEAD_MS = 5 * 365 * 24 * 60 * 60 * 1000;
|
||||
*/
|
||||
@Injectable()
|
||||
export class RemindersService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly settingsService: SettingsService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Ist die E-Mail-Erinnerung fuer diesen Benutzer moeglich? (E-09: „E-Mail-
|
||||
* Versand eingerichtet“ heisst, der Mandant hat eine `SmtpConfig`-Zeile —
|
||||
* dieselbe Regel wie `TenderMailService`; der Umgebungs-Rueckfall des
|
||||
* `MailService` zaehlt nicht.) Der Benutzer wird ueber den gebundenen Klienten
|
||||
* gelesen.
|
||||
*/
|
||||
async getEmailAvailability(tenantId: string, userId: string) {
|
||||
const tenantPrisma = forTenant(this.prisma, tenantId, userId);
|
||||
const user = await tenantPrisma.user.findFirst({
|
||||
where: { id: userId, tenantId },
|
||||
select: { email: true },
|
||||
});
|
||||
const smtp = await this.settingsService.getSmtpConfig(tenantId);
|
||||
return { smtpConfigured: smtp !== null, hasEmail: Boolean(user?.email) };
|
||||
}
|
||||
|
||||
/** 400, wenn `emailEnabled: true` verlangt wird, obwohl E-Mail nicht moeglich ist. */
|
||||
private async assertEmailAvailable(tenantId: string, userId: string) {
|
||||
const { smtpConfigured, hasEmail } = await this.getEmailAvailability(tenantId, userId);
|
||||
if (!smtpConfigured || !hasEmail) {
|
||||
throw new BadRequestException('E-Mail-Erinnerungen sind nicht möglich');
|
||||
}
|
||||
}
|
||||
|
||||
/** Die eigenen Erinnerungen, die naechste Faelligkeit zuerst. */
|
||||
async list(tenantId: string, userId: string) {
|
||||
@@ -54,6 +83,7 @@ export class RemindersService {
|
||||
|
||||
async create(tenantId: string, userId: string, dto: CreateReminderDto) {
|
||||
const dueAt = this.assertValidDueAt(dto.dueAt);
|
||||
if (dto.emailEnabled === true) await this.assertEmailAvailable(tenantId, userId);
|
||||
const tenantPrisma = forTenant(this.prisma, tenantId, userId);
|
||||
const count = await tenantPrisma.reminder.count({ where: { tenantId, userId } });
|
||||
if (count >= MAX_REMINDERS_PER_USER) {
|
||||
@@ -68,6 +98,7 @@ export class RemindersService {
|
||||
title: dto.title,
|
||||
description: dto.description ?? '',
|
||||
dueAt,
|
||||
emailEnabled: dto.emailEnabled === true,
|
||||
},
|
||||
select: REMINDER_SELECT,
|
||||
});
|
||||
@@ -83,10 +114,14 @@ export class RemindersService {
|
||||
if (row.dueAt.getTime() <= Date.now()) {
|
||||
throw new ConflictException('Die Erinnerung ist bereits fällig');
|
||||
}
|
||||
const data: { title?: string; description?: string; dueAt?: Date } = {};
|
||||
const data: { title?: string; description?: string; dueAt?: Date; emailEnabled?: boolean } = {};
|
||||
if (dto.title !== undefined) data.title = dto.title;
|
||||
if (dto.description !== undefined) data.description = dto.description;
|
||||
if (dto.dueAt !== undefined) data.dueAt = this.assertValidDueAt(dto.dueAt);
|
||||
if (dto.emailEnabled !== undefined) {
|
||||
if (dto.emailEnabled) await this.assertEmailAvailable(tenantId, userId);
|
||||
data.emailEnabled = dto.emailEnabled;
|
||||
}
|
||||
return tenantPrisma.reminder.update({
|
||||
where: { id, tenantId, userId },
|
||||
data,
|
||||
|
||||
Reference in New Issue
Block a user